package pub.doric.devkit.ui;

import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

import pub.doric.Doric;
import pub.doric.DoricContext;
import pub.doric.DoricContextManager;
import pub.doric.devkit.DoricDebugDriver;
import pub.doric.devkit.DoricDev;
import pub.doric.devkit.R;
import pub.doric.devkit.qrcode.DisplayUtil;
import pub.doric.devkit.qrcode.activity.CaptureActivity;
import pub.doric.devkit.qrcode.activity.CodeUtils;

public class DoricDevActivity extends AppCompatActivity implements DoricDev.StatusCallback {
    private int REQUEST_CODE = 100;
    private ContextCellAdapter cellAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DisplayUtil.initDisplayOpinion(getApplicationContext());
        setContentView(R.layout.layout_debug_context);
        initHeaders();
        initList();
    }

    private void initList() {
        RecyclerView recyclerView = findViewById(R.id.list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        this.cellAdapter = new ContextCellAdapter();
        recyclerView.setAdapter(this.cellAdapter);
    }

    @Override
    protected void onStart() {
        super.onStart();
        DoricDev.getInstance().addStatusCallback(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        DoricDev.getInstance().removeStatusCallback(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    Intent intent = new Intent(DoricDevActivity.this, CaptureActivity.class);
                    startActivityForResult(intent, REQUEST_CODE);
                }
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (null != data) {
            Bundle bundle = data.getExtras();
            if (bundle == null) {
                return;
            }
            if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
                String result = bundle.getString(CodeUtils.RESULT_STRING);
                DoricDev.getInstance().connectDevKit("ws://" + result + ":7777");
            }
        }
    }


    private void initHeaders() {
        TextView tvConnection = findViewById(R.id.tv_connect_info);
        TextView tvInput = findViewById(R.id.tv_input);
        TextView tvScan = findViewById(R.id.tv_scan);
        TextView tvDisconnect = findViewById(R.id.tv_disconnect);
        if (DoricDev.getInstance().isInDevMode()) {
            tvConnection.setText(DoricDev.getInstance().getIP());
            tvInput.setVisibility(View.GONE);
            tvScan.setVisibility(View.GONE);
            tvDisconnect.setVisibility(View.VISIBLE);
            tvConnection.setBackgroundColor(Color.parseColor("#2ed573"));
        } else {
            tvConnection.setText("Disconnected");
            tvDisconnect.setVisibility(View.GONE);
            tvInput.setVisibility(View.VISIBLE);
            tvScan.setVisibility(View.VISIBLE);
            tvConnection.setBackgroundColor(Color.parseColor("#a4b0be"));
        }

        tvScan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (DoricDev.getInstance().isRunningInEmulator) {
                    DoricDev.getInstance().connectDevKit("ws://" + "10.0.2.2" + ":7777");
                } else {
                    if (ContextCompat.checkSelfPermission(DoricDevActivity.this, Manifest.permission.CAMERA)
                            != PackageManager.PERMISSION_GRANTED) {
                        if (ActivityCompat.shouldShowRequestPermissionRationale(DoricDevActivity.this,
                                Manifest.permission.CAMERA)) {
                        } else {
                            ActivityCompat.requestPermissions(DoricDevActivity.this,
                                    new String[]{Manifest.permission.CAMERA,}, 1);
                        }
                    } else {
                        Intent intent = new Intent(DoricDevActivity.this, CaptureActivity.class);
                        startActivityForResult(intent, REQUEST_CODE);
                    }
                }
            }
        });

        tvInput.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View clickView) {
                if (DoricDev.getInstance().isRunningInEmulator) {
                    DoricDev.getInstance().connectDevKit("ws://" + "10.0.2.2" + ":7777");
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(DoricDevActivity.this, R.style.Theme_Doric_Modal_Prompt);
                    builder.setTitle("Please input devkit ip");
                    View v = LayoutInflater.from(DoricDevActivity.this).inflate(R.layout.doric_modal_prompt, null);
                    final EditText editText = v.findViewById(R.id.edit_input);
                    editText.setHint("192.168.1.1");
                    String ip = DoricDev.getInstance().getIP();
                    if (!TextUtils.isEmpty(ip)) {
                        editText.setText(ip);
                        editText.setSelection(ip.length());
                    }
                    builder.setView(v);
                    builder
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    String ip = editText.getText().toString();
                                    DoricDev.getInstance().connectDevKit("ws://" + ip + ":7777");
                                }
                            })
                            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                }
                            });
                    builder.show();
                }
            }
        });
        tvDisconnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DoricDev.getInstance().closeDevMode();
            }
        });
    }

    @Override
    public void onOpen(String url) {
        initHeaders();
        this.cellAdapter.notifyDataSetChanged();
    }

    @Override
    public void onClose(String url) {
        initHeaders();
        this.cellAdapter.notifyDataSetChanged();
    }

    @Override
    public void onFailure(Throwable throwable) {
        initHeaders();
        this.cellAdapter.notifyDataSetChanged();
    }

    @Override
    public void onReload(DoricContext context, String script) {
        this.cellAdapter.notifyDataSetChanged();
    }

    @Override
    public void onStartDebugging(DoricContext context) {
        this.cellAdapter.notifyDataSetChanged();
    }

    @Override
    public void onStopDebugging() {
        this.cellAdapter.notifyDataSetChanged();
    }

    private static class ContextCellHolder extends RecyclerView.ViewHolder {
        public TextView tvId;
        public TextView tvSource;
        public ImageView ivDebug;
        public View layoutBtn;

        public ContextCellHolder(@NonNull View itemView) {
            super(itemView);
        }
    }

    private static class ContextCellAdapter extends RecyclerView.Adapter<ContextCellHolder> {
        private final ArrayList<DoricContext> contexts = new ArrayList<>();
        private Bitmap icon_off;
        private Bitmap icon_on;
        private String debug_off = "[encoded data, 4564 characters]";
        private String debug_on = "[encoded data, 4692 characters]";

        private ContextCellAdapter() {
            this.contexts.addAll(DoricContextManager.aliveContexts());
            this.icon_off = getIcon(debug_off);
            this.icon_on = getIcon(debug_on);
        }

        private Bitmap getIcon(String str) {
            byte[] data = Base64.decode(str, Base64.DEFAULT);
            return BitmapFactory.decodeByteArray(data, 0, data.length);
        }

        @NonNull
        @Override
        public ContextCellHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View cell = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_debug_context_cell, parent, false);
            ContextCellHolder cellHolder = new ContextCellHolder(cell);
            cellHolder.tvId = cell.findViewById(R.id.context_id_text_view);
            cellHolder.tvSource = cell.findViewById(R.id.source_text_view);
            cellHolder.ivDebug = cell.findViewById(R.id.icon_debug);
            cellHolder.layoutBtn = cell.findViewById(R.id.layout_btn);
            return cellHolder;
        }

        @Override
        public void onBindViewHolder(@NonNull final ContextCellHolder holder, int position) {
            final DoricContext context = contexts.get(position);
            holder.tvId.setText(context.getContextId());
            holder.tvSource.setText(context.getSource());
            holder.ivDebug.setImageBitmap(DoricDev.getInstance().isInDevMode() ? icon_on : icon_off);
            holder.itemView.setBackgroundColor(position % 2 == 0 ? Color.parseColor("#ecf0f1") : Color.parseColor("#bdc3c7"));
            if (DoricDev.getInstance().isReloadingContext(context)) {
                holder.itemView.setBackgroundColor(Color.parseColor("#ffeaa7"));
            }
            if (context.getDriver() instanceof DoricDebugDriver) {
                holder.itemView.setBackgroundColor(Color.parseColor("#fab1a0"));
            }
            holder.layoutBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (DoricDev.getInstance().isInDevMode()) {
                        final String items[] = {"View source",};
                        AlertDialog.Builder builder = new AlertDialog.Builder(holder.itemView.getContext(), R.style.Theme_Doric_Modal);
                        builder.setTitle(String.format("%s %s", context.getContextId(), context.getSource()));
                        builder.setIcon(new BitmapDrawable(icon_on));
                        builder.setItems(items, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (which == 0) {
                                    Toast.makeText(Doric.application(), "View source", Toast.LENGTH_LONG).show();
                                }
                                dialog.dismiss();
                            }
                        });
                        builder.create().show();
                    } else {
                        Toast.makeText(Doric.application(), "Please connect to devkit first", Toast.LENGTH_LONG).show();
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return this.contexts.size();
        }
    }
}
