package com.dragontcp.client;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

public class LogActivity extends Activity {
    private static final int BG = Color.rgb(11, 15, 20);
    private static final int CARD = Color.rgb(22, 28, 36);
    private static final int BORDER = Color.rgb(43, 53, 66);
    private static final int TEXT = Color.rgb(244, 247, 251);
    private static final int MUTED = Color.rgb(139, 151, 168);
    private static final int LOG_BG = Color.rgb(7, 10, 14);
    private static final int LOG_TEXT = Color.rgb(179, 194, 214);

    private TextView logText;
    private ScrollView logScroll;

    private final AppLog.Listener logListener = line -> runOnUiThread(() -> appendLogLine(line));

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        forceDarkSystemUi();
        buildUi();
    }

    @Override
    protected void onStart() {
        super.onStart();
        logText.setText(AppLog.history());
        AppLog.addListener(logListener);
        logScroll.post(this::scrollLogToBottom);
    }

    @Override
    protected void onStop() {
        AppLog.removeListener(logListener);
        super.onStop();
    }

    private void forceDarkSystemUi() {
        Window w = getWindow();
        w.setStatusBarColor(BG);
        w.setNavigationBarColor(Color.rgb(7, 10, 14));
        if (Build.VERSION.SDK_INT >= 26) w.getDecorView().setSystemUiVisibility(0);
    }

    private void buildUi() {
        LinearLayout root = new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);
        root.setBackgroundColor(BG);
        root.setPadding(dp(16), dp(14), dp(16), dp(12));

        LinearLayout header = new LinearLayout(this);
        header.setOrientation(LinearLayout.HORIZONTAL);
        header.setGravity(Gravity.CENTER_VERTICAL);
        header.setPadding(dp(2), dp(2), dp(2), dp(12));

        LinearLayout heading = new LinearLayout(this);
        heading.setOrientation(LinearLayout.VERTICAL);
        TextView title = text("Logs", 25, TEXT, true);
        TextView subtitle = text("DragonTCP Lite", 12, MUTED, false);
        subtitle.setPadding(0, dp(2), 0, 0);
        heading.addView(title);
        heading.addView(subtitle);
        header.addView(heading, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));

        Button back = smallButton("BACK");
        Button clear = smallButton("CLEAR");
        LinearLayout.LayoutParams bp = new LinearLayout.LayoutParams(dp(76), dp(42));
        bp.setMarginEnd(dp(8));
        header.addView(back, bp);
        header.addView(clear, new LinearLayout.LayoutParams(dp(82), dp(42)));
        root.addView(header);

        LinearLayout panel = new LinearLayout(this);
        panel.setOrientation(LinearLayout.VERTICAL);
        panel.setPadding(dp(10), dp(10), dp(10), dp(10));
        panel.setBackground(roundRect(CARD, 16, BORDER, 1));

        logScroll = new ScrollView(this);
        logScroll.setFillViewport(true);
        logScroll.setFocusable(false);
        logScroll.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
        logScroll.setBackground(roundRect(LOG_BG, 11, Color.rgb(30, 38, 49), 1));

        logText = new TextView(this);
        logText.setTextSize(12f);
        logText.setTextColor(LOG_TEXT);
        logText.setTypeface(Typeface.MONOSPACE);
        logText.setTextIsSelectable(true);
        logText.setPadding(dp(11), dp(10), dp(11), dp(10));
        logText.setLineSpacing(0, 1.10f);
        logScroll.addView(logText, new ScrollView.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        ));

        panel.addView(logScroll, new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                0,
                1f
        ));
        root.addView(panel, new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                0,
                1f
        ));

        back.setOnClickListener(v -> finish());
        clear.setOnClickListener(v -> {
            AppLog.clear();
            logText.setText("");
            logScroll.scrollTo(0, 0);
        });

        setContentView(root);
    }

    private void appendLogLine(String line) {
        View child = logScroll.getChildAt(0);
        int contentHeight = child == null ? 0 : child.getHeight();
        int maxScroll = Math.max(0, contentHeight - logScroll.getHeight());
        boolean follow = maxScroll - logScroll.getScrollY() < dp(48);

        logText.append(line + "\n");
        if (follow) logScroll.post(this::scrollLogToBottom);
    }

    private void scrollLogToBottom() {
        View child = logScroll.getChildAt(0);
        if (child == null) return;
        int y = Math.max(0, child.getHeight() - logScroll.getHeight());
        logScroll.scrollTo(0, y);
    }

    private TextView text(String value, float size, int color, boolean bold) {
        TextView t = new TextView(this);
        t.setText(value);
        t.setTextSize(size);
        t.setTextColor(color);
        if (bold) t.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
        return t;
    }

    private Button smallButton(String value) {
        Button b = new Button(this);
        b.setText(value);
        b.setAllCaps(false);
        b.setTextSize(11);
        b.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
        b.setTextColor(TEXT);
        b.setBackground(roundRect(Color.rgb(32, 40, 51), 10, BORDER, 1));
        return b;
    }

    private GradientDrawable roundRect(int color, int radiusDp, int strokeColor, int strokeDp) {
        GradientDrawable d = new GradientDrawable();
        d.setColor(color);
        d.setCornerRadius(dp(radiusDp));
        if (strokeDp > 0) d.setStroke(dp(strokeDp), strokeColor);
        return d;
    }

    private int dp(int value) {
        return Math.round(value * getResources().getDisplayMetrics().density);
    }
}
