package com.xypower.frpandroid;

import android.app.ActivityManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;

import com.xypower.common.FilesUtils;
import com.xypower.common.LogFormatter;
import com.xypower.common.LogcatHandler;
import com.xypower.common.RotatingHandler;


import org.jetbrains.annotations.NotNull;

import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;


public class MainActivity extends AppCompatActivity {

    private static final String TAG = "FRP";
    public static final String DEFAULT_SERVER = "61.169.135.146";
    private static final String DEFAULT_PROXY_NAME = "p2p_";
    public static final int DEFAULT_PORT = 7000;
    public static final int DEFAULT_REMOTE_PORT = 50001;

    private Switch state_switch;
    private Switch auto_start_switch;
    private ShellService mService;
    private boolean mBound;

    private static final String MICRO_KEY_SERVER = "%%SERVER%%";
    private static final String MICRO_KEY_PORT = "%%PORT%%";
    private static final String MICRO_KEY_REMOTE_PORT = "%%REMOTE_PORT%%";
    private static final String MICRO_KEY_PROXY_NAME = "%%PROXY_NAME%%";

    Handler mHandler;

    public Logger logger;

    private String mServer = DEFAULT_SERVER;
    private int mPort = DEFAULT_PORT;
    private int mRemotePort = DEFAULT_REMOTE_PORT;
    private String mProxyName = Long.toString(System.currentTimeMillis() / 1000);

    private final ServiceConnection connection = new ServiceConnection() {
        public void onServiceConnected(@NotNull ComponentName className, @NotNull IBinder service) {
            // Intrinsics.checkNotNullParameter(className, "className");
            // Intrinsics.checkNotNullParameter(service, "service");
            ShellService.LocalBinder binder = (ShellService.LocalBinder)service;
            MainActivity.this.mService = binder.getService();
            MainActivity.this.mBound = true;
            MainActivity.this.state_switch.setChecked(true);
        }

        public void onServiceDisconnected(@NotNull ComponentName arg0) {
            // Intrinsics.checkNotNullParameter(arg0, "arg0");
            MainActivity.this.mBound = false;
            MainActivity.this.state_switch.setChecked(false);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHandler = new Handler();

        logger = Logger.getLogger("com.xypower.frp.logger");
        logger.setLevel(Level.ALL);
        // LogFormatter.installFormatter(logger);
        LogFormatter logFormatter = new LogFormatter();

        if (BuildConfig.DEBUG) {
            LogcatHandler logcatHandler = new LogcatHandler(TAG);
            logcatHandler.setFormatter(logFormatter);
            logger.addHandler(logcatHandler);
        }

        RotatingHandler rotatingHandler = null;
        try {
            File logFile = new File(getDataDir(), "frplog.txt");
            if (logFile.exists()) {
                logFile.delete();
            }

            rotatingHandler = new RotatingHandler(logFile.getAbsolutePath(), logFormatter);

            logger.addHandler(rotatingHandler);

        } catch (Throwable e) {
            System.out.println("Failed to create directory:" + e.getMessage());
        }

        logger.info("FrpAndroid is launching");

        String versionName = null;
        try {
            versionName = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        ActionBar actionBar = getSupportActionBar();
        actionBar.setTitle(actionBar.getTitle().toString() + " v" + versionName + "/0.58.0");

        int startFrp = 0;
        int autoClose = 0;
        {
            Intent intent = getIntent();
            String stringVal = intent.getStringExtra("server");
            if (!TextUtils.isEmpty(stringVal)) {
                mServer = stringVal;
            }
            stringVal = intent.getStringExtra("proxyName");
            if (!TextUtils.isEmpty(stringVal)) {
                mProxyName = stringVal;
            }
            mPort = intent.getIntExtra("port", DEFAULT_PORT);
            mRemotePort = intent.getIntExtra("remotePort", DEFAULT_REMOTE_PORT);
            startFrp = intent.getIntExtra("startFrp", 0);

            if (startFrp != 0) {
                Log.i(TAG, "Will start server");
            }

            autoClose = intent.getIntExtra("autoClose", 0);

        }

        checkConfig(getApplicationContext(), mServer, mPort, mRemotePort, mProxyName);
        checkNotificationPermission();
        createBGNotificationChannel();

        mBound = isServiceRunning(ShellService.class);
        state_switch = (Switch)this.findViewById(R.id.state_switch);
        // Intrinsics.checkNotNullExpressionValue(var10001, "findViewById<SwitchCompat>(R.id.state_switch)");

        state_switch.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener)(new CompoundButton.OnCheckedChangeListener() {
            public final void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    MainActivity.this.startShell();
                } else {
                    MainActivity.this.stopShell();
                }
            }
        }));

        final SharedPreferences editor = this.getSharedPreferences("data", 0);
        auto_start_switch = (Switch) this.findViewById(R.id.auto_start_switch);
        // Intrinsics.checkNotNullExpressionValue(var10001, "findViewById<SwitchCompat>(R.id.auto_start_switch)");

        auto_start_switch.setChecked(editor.getBoolean("auto_start", false));

        auto_start_switch.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener)(new CompoundButton.OnCheckedChangeListener() {
            public final void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                SharedPreferences.Editor editorx = editor.edit();
                editorx.putBoolean("auto_start", isChecked);
                editorx.apply();
            }
        }));

        if (mBound) {
            try {
                Intent intent = new Intent((Context) this, ShellService.class);
                bindService(intent, (ServiceConnection) this.connection, Context.BIND_AUTO_CREATE);
                logger.info("Binded service");
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
            }
        }

        setListener();

        state_switch.setChecked(mBound || (startFrp != 0));

        if (autoClose != 0) {

            logger.info("Server stopped");
            try {
                stopShell();
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
            }
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    MainActivity.this.finish();
                }
            }, 2000);
        }
    }

    protected void onDestroy() {
        super.onDestroy();
        //
    }

    private final void setListener() {
        Button configButton = (Button)findViewById(R.id.configButton);
        configButton.setOnClickListener((View.OnClickListener)(new View.OnClickListener() {
            public final void onClick(View it) {
                Intent intent = new Intent((Context)MainActivity.this, ConfigActivity.class);
                intent.putExtras(getIntent());
                MainActivity.this.startActivity(intent);
            }
        }));

        Button refreshButton = (Button)findViewById(R.id.refreshButton);
        refreshButton.setOnClickListener((View.OnClickListener)(new View.OnClickListener() {
            public final void onClick(View it) {
                MainActivity.this.readLog();
            }
        }));
        Button deleteButton = (Button)findViewById(R.id.deleteButton);
        deleteButton.setOnClickListener((View.OnClickListener)(new View.OnClickListener() {
            public final void onClick(View it) {
                MainActivity.this.mService.clearOutput();
                MainActivity.this.readLog();
            }
        }));
    }

    public final void readLog() {
        TextView logTextView = (TextView)findViewById(R.id.logTextView);
        if (mBound) {
            if (mService != null) {
                logTextView.setText((CharSequence)mService.getOutput());
            }
        } else {
            Log.w("adx", "readLog mBound==null");
        }

    }

    public static File checkConfig(Context context, String server, int port, int remotePort, String proxyName) {
        // Intrinsics.checkNotNullExpressionValue(var12, "resources");
        AssetManager assetmanager = context.getResources().getAssets();

        File confFile = new File(context.getDataDir(), "conf");
        if (!confFile.exists()) {
            confFile.mkdirs();
        }
        File file = new File(new File(context.getDataDir(), "conf"), "config.toml");

        StringBuffer configContent = new StringBuffer();
        InputStream inputStream = null;
        try {
            inputStream = assetmanager.open("config.toml");
            String content = FilesUtils.readTextFile(inputStream);
            content = content.replaceAll(MICRO_KEY_SERVER, server);
            content = content.replaceAll(MICRO_KEY_PORT, Integer.toString(port));
            content = content.replaceAll(MICRO_KEY_REMOTE_PORT, Integer.toString(remotePort));
            content = content.replaceAll(MICRO_KEY_PROXY_NAME, proxyName);

            FilesUtils.writeTextFile(file.getAbsolutePath(), content);
        } catch (Throwable ex) {
            ex.printStackTrace();
        } finally {
            FilesUtils.closeFriendly(inputStream);
        }

        try {
            // Toml toml = new Toml();
            // File file = new File(getDataDir(), "config.toml");
            // toml.read(file);
            // int aa = 0;
            // String someValue = toml.getString("someKey");
            // Date someDate = toml.getDate("someTable.someDate");
            // MyClass myClass = toml.to(MyClass.class);
            // TomlWriter.Builder tomlBuilder = new TomlWriter.Builder();
            // tomlBuilder.

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return file;
    }

    private final void startShell() {
        logger.info("Start Shell");
        try {
            Intent intent = new Intent(getApplicationContext(), ShellService.class);
            intent.putExtra("filename", "libfrpc.so");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(intent);
            } else {
                startService(intent);
            }
            bindService(intent, (ServiceConnection) connection, Context.BIND_AUTO_CREATE);
        } catch (Exception ex) {
            logger.warning(ex.getMessage());
        }
    }

    private final void stopShell() {
        try {
            Intent intent = new Intent((Context) this, ShellService.class);
            unbindService((ServiceConnection) connection);
            stopService(intent);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private final void checkNotificationPermission() {
        // Intrinsics.checkNotNullExpressionValue(this.registerForActivityResult((ActivityResultContract)(new RequestPermission()), (ActivityResultCallback)null.INSTANCE), "registerForActivityResul….\n            }\n        }");
    }

    private final void createBGNotificationChannel() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            String name = "frp后台服务";
            String descriptionText = "frp后台服务通知";
            NotificationChannel notificationChannel = null;

            notificationChannel = new NotificationChannel("shell_bg", (CharSequence)name, NotificationManager.IMPORTANCE_MIN);

            notificationChannel.setDescription(descriptionText);
            NotificationChannel channel = notificationChannel;
            NotificationManager notificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
            if (notificationManager == null) {
                throw new NullPointerException("null cannot be cast to non-null type android.app.NotificationManager");
            }

            notificationManager.createNotificationChannel(channel);
        }

    }

    private final boolean isServiceRunning(Class serviceClass) {
        ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        if (activityManager != null) {
            Iterator it = activityManager.getRunningServices(Integer.MAX_VALUE).iterator();

            ComponentName componentName;
            String className;
            do {
                if (!it.hasNext()) {
                    return false;
                }

                ActivityManager.RunningServiceInfo serviceInfo = (ActivityManager.RunningServiceInfo)it.next();
                className = serviceClass.getName();
                componentName = serviceInfo.service;
                // Intrinsics.checkNotNullExpressionValue(var10001, "service.service");
            } while(!className.equalsIgnoreCase(componentName.getClassName()));
        }

        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // Back pressed
            return true; // disable it
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        //当点击不同的menu item 是执行不同的操作
        switch (id) {
            case R.id.action_exit: {
                stopShell();

                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        MainActivity.this.finish();
                        System.exit(0);
                    }
                }, 2000);
            }
            break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }


}