package com.xugame.gameconsole.emulator;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.hardware.input.InputManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;

import com.retroarch.browser.retroactivity.AspectRatio;
import com.xugame.app.AppSystem;
import com.xugame.app.EnvironmentCallback;
import com.xugame.bean.InputCode;
import com.xugame.bean.InputDescriptorBean;
import com.xugame.gameconsole.dialog.gamemenu.GameMenuDialog;
import com.xugame.gameconsole.dialog.gamemenu.GameMenuDialogListener;
import com.xugame.gameconsole.preferences.ConfigFile;
import com.xugame.gameconsole.preferences.UserPreferences;
import com.xugame.gameconsole.util.DebugUtil;
import com.xugame.gameconsole.util.Util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//private void parserIntent() {
//        Intent intent = getIntent();
//        romPath = intent.getStringExtra("rom_path");
//        romPath = intent.getStringExtra("rom_path");
//        libsPath = intent.getStringExtra("lib_path");
//        configPath = intent.getStringExtra("config_path");
//        }
public class RetroArchEmulatorActivity extends RetroActivityCamera {
    private static final String TAG = "RetroArchEmulatorActivityTAG";
    private ScreenType mScreenType = ScreenType.NORMAL;
    private boolean mUpdateScreen = false;
    // If set to true then Retroarch will completely exit when it loses focus
    private boolean quitfocus = false;

    private AppSystem system = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        system = new AppSystem();

        callback = new EnvironmentCallback() {
            @Override
            public void setInputDescriptors(InputDescriptorBean[] descriptors) {
                for (int i = 0; i < descriptors.length; i++) {
                    Log.i(
                            "EnvironmentCallback",
                            "i: " + i
                                    + ", port: " + descriptors[i].getPort()
                                    + ", device: " + descriptors[i].getDevice()
                                    + ", index: " + descriptors[i].getIndex()
                                    + ", id: " + descriptors[i].getId()
                                    + ", desc: " + descriptors[i].getDescription()
                    );

                    if (descriptors[i].getPort() >= AppSystem.MAX_USERS)
                        continue;

                    if (descriptors[i].getId() >= 16)
                        continue;

                    if (descriptors[i].getDevice() == AppSystem.DEVICE_JOYPAD) {
                        system.inputDescriptors[descriptors[i].getPort()]
                                [descriptors[i].getId()] = descriptors[i].getDescription();
                    } else if (descriptors[i].getDevice() == AppSystem.DEVICE_ANALOG) {
                        if (descriptors[i].getId() == AppSystem.DEVICE_ID_ANALOG_X) {
                            if (descriptors[i].getIndex() == AppSystem.DEVICE_INDEX_ANALOG_LEFT) {
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_LEFT_X_PLUS] = descriptors[i].getDescription();
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_LEFT_X_MINUS] = descriptors[i].getDescription();
                            } else if (descriptors[i].getIndex() == AppSystem.DEVICE_INDEX_ANALOG_RIGHT) {
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_RIGHT_X_PLUS] = descriptors[i].getDescription();
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_RIGHT_X_MINUS] = descriptors[i].getDescription();
                            }
                        } else if (descriptors[i].getId() == AppSystem.DEVICE_ID_ANALOG_Y) {
                            if (descriptors[i].getIndex() == AppSystem.DEVICE_INDEX_ANALOG_LEFT) {
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_LEFT_Y_PLUS] = descriptors[i].getDescription();
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_LEFT_Y_MINUS] = descriptors[i].getDescription();
                            } else if (descriptors[i].getIndex() == AppSystem.DEVICE_INDEX_ANALOG_RIGHT) {
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_RIGHT_Y_PLUS] = descriptors[i].getDescription();
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [InputCode.ANALOG_RIGHT_Y_MINUS] = descriptors[i].getDescription();
                            }
                        } else if (descriptors[i].getId() == AppSystem.DEVICE_ID_JOYPAD_L2
                                || descriptors[i].getId() == AppSystem.DEVICE_ID_JOYPAD_R2
                        ) {
                            if (descriptors[i].getIndex() == AppSystem.DEVICE_INDEX_ANALOG_BUTTON) {
                                system.inputDescriptors[descriptors[i].getPort()]
                                        [descriptors[i].getId()] = descriptors[i].getDescription();
                            }
                        }
                    }
                }

                system.hasInputDescriptors = true;
            }
        };
    }

    @Override
    public void showLocalExitDialog() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                showDialog();
            }
        });

        DebugUtil.i(TAG, "showLocalExitDialog");
    }

    @Override
    public void onResume() {
        super.onResume();

        setSustainedPerformanceMode(sustainedPerformanceMode);

        if (Build.VERSION.SDK_INT >= 19) {
            // Immersive mode

            // Constants from API > 14
            final int API_SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
            final int API_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
            final int API_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
            final int API_SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
            final int API_SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;

            View thisView = getWindow().getDecorView();
            thisView.setSystemUiVisibility(API_SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | API_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | API_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | API_SYSTEM_UI_FLAG_FULLSCREEN
                    | API_SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

            // Check for Android UI specific parameters
            Intent retro = getIntent();

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                String refresh = retro.getStringExtra("REFRESH");

                // If REFRESH parameter is provided then try to set refreshrate accordingly
                if (refresh != null) {
                    WindowManager.LayoutParams params = getWindow().getAttributes();
                    params.preferredRefreshRate = Integer.parseInt(refresh);
                    getWindow().setAttributes(params);
                }
            }

            // If QUITFOCUS parameter is provided then enable that Retroarch quits when focus is lost
            quitfocus = retro.hasExtra("QUITFOCUS");

            // If HIDEMOUSE parameters is provided then hide the mourse cursor
            // This requires NVIDIA Android extensions (available on NVIDIA Shield), if they are not
            // available then nothing will be done
            if (retro.hasExtra("HIDEMOUSE")) hideMouseCursor();
            int screenMode = retro.getIntExtra("screenMode", 0);
            if (screenMode >= 0 && screenMode < 3) {
                switch (screenMode) {
                    case 0:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_CORE.getValue());
                        break;
                    case 1:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_FULL.getValue());
                        break;
                    case 2:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_CUSTOM.getValue());
                        setCustomViewPort(Util.getSize(420), Util.getSize(87), Util.getSize(1080), Util.getSize(810));
                        break;
                }
            }
        }

        //Checks if Android versions is above 9.0 (28) and enable the screen to write over notch if the user desires
        if (Build.VERSION.SDK_INT >= 28) {
            ConfigFile configFile = new ConfigFile(UserPreferences.getDefaultConfigPath(this));
            try {
                if (configFile.getBoolean("video_notch_write_over_enable")) {
                    getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
                }
            } catch (Exception e) {
                Log.w("Key doesn't exist yet.", e.getMessage());
            }
        }
    }

    public void hideMouseCursor() {

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
            // Check for NVIDIA extensions and minimum SDK version
            Method mInputManager_setCursorVisibility;
            try {
                mInputManager_setCursorVisibility =
                        InputManager.class.getMethod("setCursorVisibility", boolean.class);
            } catch (NoSuchMethodException ex) {
                return; // Extensions were not available so do nothing
            }

            // Hide the mouse cursor
            InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
            try {
                mInputManager_setCursorVisibility.invoke(inputManager, false);
            } catch (InvocationTargetException ite) {
            } catch (IllegalAccessException iae) {
            }
        }
    }

    @Override
    public void onStop() {
        super.onStop();

        // If QUITFOCUS parameter was set then completely exit Retroarch when focus is lost
        if (quitfocus) System.exit(0);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        DebugUtil.i(TAG, "" + event.getKeyCode());
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && event.getAction() == KeyEvent.ACTION_DOWN) {
//            showDialog();
            Intent intent = new Intent();//调出主菜单UI
            ComponentName componentName = new ComponentName("com.xugame.gameconsoleMenu",
                    "com.xugame.gameconsole.dialog.localgamesetting.LocalGameSettingDialog");
            intent.setComponent(componentName);
            startActivityForResult(intent, 200);
            return super.dispatchKeyEvent(event);
        }

        return super.dispatchKeyEvent(event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        DebugUtil.i(TAG, "onKeyDown=" + event.getKeyCode());
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        if (mUpdateScreen) {
            switch (mScreenType) {
                case NORMAL:
                    switchFilter(null);
                    break;
                case SAI_2X:
                    switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/2xSaI.filt");
                    break;
                case SCANLINE:
                    switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scanline2x.filt");
                    break;
            }
        }

        super.onWindowFocusChanged(hasFocus);
    }

    private void showDialog() {
        GameMenuDialog menuDialog = new GameMenuDialog(this, new GameMenuDialogListener() {
            @Override
            public void onExitGame() {
                exitLocalGame();
                finish();
            }

            @Override
            public void onResumeGame(ScreenType type, int archiveIndex) {
                mScreenType = type;
                mUpdateScreen = true;
                gameDialogClosed();
            }

            @Override
            public boolean onSaveState(int stateIndex) {
                // Toast.makeText(mContext, "写入存档" + stateIndex, Toast.LENGTH_SHORT).show();
                return saveState(stateIndex);
            }

            @Override
            public boolean onLoadState(int stateIndex) {
                // Toast.makeText(mContext,"读取存档"+stateIndex,Toast.LENGTH_SHORT).show();
                return loadState(stateIndex);
            }

            @Override
            public void onKeySettingNums(int[] keys) {
                for (int i = 0; i < keys.length; i++) {
                    setInputKeys(0, i, keys[i]);
                }
                saveOverrideConfig();
            }

            @Override
            public void onSetRatio(int type) {
                switch (type) {
                    case 0:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_CORE.getValue());
                        break;
                    case 1:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_FULL.getValue());
                        break;
                    case 2:
                        setAspectRatio(AspectRatio.ASPECT_RATIO_CUSTOM.getValue());
                        setCustomViewPort(100, 100, 480, 320);
                        break;
                }
            }
        });
        menuDialog.setCanceledOnTouchOutside(true);
        menuDialog.show();


//        AlertDialog.Builder alertDialog = new ProgressDialog.Builder(this)
//                .setTitle("Yes/No")
//                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
//                    @Override
//                    public void onClick(DialogInterface dialog, int which) {
//                        clickBack();
//                        dialog.dismiss();
//                    }
//                })
//                .setNegativeButton("No", new DialogInterface.OnClickListener() {
//                    @Override
//                    public void onClick(DialogInterface dialog, int which) {
//                        dialog.dismiss();
//                    }
//                })
//                .setMessage("退出游戏？");
//        alertDialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 200) {
            if (resultCode == 201) {//继续游戏
                if (data != null) {
                    int scanLine = data.getIntExtra("scanLine", 0);
                    int screen = data.getIntExtra("screen", 0);
                    DebugUtil.i(TAG, "scanline=" + scanLine + "screen=" + screen);

                    if (screen >= 0 && screen < 3) {
                        switch (screen) {
                            case 0:
                                setAspectRatio(AspectRatio.ASPECT_RATIO_CORE.getValue());
                                break;
                            case 1:
                                setAspectRatio(AspectRatio.ASPECT_RATIO_FULL.getValue());
                                break;
                            case 2:
                                setAspectRatio(AspectRatio.ASPECT_RATIO_CUSTOM.getValue());
                                setCustomViewPort(Util.getSize(420), Util.getSize(87), Util.getSize(1080), Util.getSize(810));
                                break;
                        }
                    }
                    if (scanLine >= 0 && scanLine < 3) {
                        switch (ScreenType.values()[scanLine]) {
                            case NORMAL:
                                switchFilter(null);
                                break;
                            case SAI_2X:
                                switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/2xSaI.filt");
                                break;
                            case SCANLINE:
                                switchFilter("/data/user/0/com.xugame.gameconsole/filters/video/Scanline2x.filt");
                                break;
                        }
                    }
                }
            } else if (resultCode == 0) {
                exitLocalGame();
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}
