package com.xixun.xixunplayer;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.Choreographer;
import android.view.View;

import androidx.annotation.NonNull;

import java.util.Calendar;
import java.util.TimeZone;

import gnph.util.JSMap;

@SuppressLint("ViewConstructor")
public class SrcAnaClock extends View implements Choreographer.FrameCallback {

    Calendar calendar;
    Bitmap img;
    int pinHourColor, pinMinColor, pinSecColor;
    Path hPath, mPath, sPath;
    float hAngle, mAngle, sAngle;
    Paint paintPin = new Paint(), paint = new Paint();
    boolean showSecHand;

    public SrcAnaClock(Prog prog, float w, float h, String path, JSMap source) {
        super(prog.getContext());
        var timeZoneStr = source.str("timeZone");
        //if(timeZoneStr!=null) timeZone = ZoneId.of(timeZoneStr);
        var timeZone = timeZoneStr==null ? null : TimeZone.getTimeZone(timeZoneStr);
        calendar = timeZone==null ? Calendar.getInstance() : Calendar.getInstance(timeZone);

        var sideLen = Math.min(w, h);
        var halfSide = sideLen / 2;
        var lineWidth = sideLen / 128;
        if(lineWidth < 1) lineWidth = 1;

        paintPin.setAntiAlias(true);
        paintPin.setStyle(Paint.Style.FILL_AND_STROKE);
        paintPin.setStrokeWidth(lineWidth);
        paintPin.setStrokeJoin(Paint.Join.ROUND);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        var fontSize = sideLen / 11;
        paint.setTextSize(fontSize);

        img = BitmapFactory.decodeFile(path);
        if(img==null) {
            img = Bitmap.createBitmap((int)w, (int)h, Bitmap.Config.ARGB_8888);
            var canvas = new Canvas(img);
            canvas.translate(w / 2, h / 2);
            if(source.bool("showBg")) {
                var bgColor = Color.parseColor(source.stnn("bgColor"));
                var opacity = source.dbl("opacity", -1);
                if(opacity!=-1) bgColor = bgColor & 0x00ffffff | ((int)opacity*255)<<24;
                paint.setColor(bgColor);
                canvas.drawOval(-halfSide, -halfSide, halfSide, halfSide, paint);
            }
            var minMarkSize = sideLen/48;
            var hourMarkSize = sideLen/32;
            var scaleHourColor = Color.parseColor(source.stnn("scaleHourColor"));
            var scaleMinColor = Color.parseColor(source.stnn("scaleMinColor"));
            var showScaleNum = source.bool("showScaleNum");
            var rScale = (sideLen - Math.max(minMarkSize, hourMarkSize)) / 2;
            var rNum = halfSide * 0.83;
            for(int i=0; i<60; i++) {
                var k = i * Math.PI / 30;
                var x = (float) (Math.sin(k) * rScale);
                var y = (float) (-Math.cos(k) * rScale);
                if(i % 5 > 0) {
                    var rr = minMarkSize / 2f;
                    paint.setColor(scaleMinColor);
                    canvas.drawOval(x-rr, y-rr, x+rr, y+rr, paint);
                } else {
                    var rr = hourMarkSize / 2f;
                    paint.setColor(scaleHourColor);
                    canvas.drawOval(x-rr, y-rr, x+rr, y+rr, paint);
                    if(showScaleNum) {
                        var hour = i/5;
                        if(hour==0) hour = 12;
                        x = (float) (Math.sin(k) * rNum);
                        y = (float) (-Math.cos(k) * rNum);
                        canvas.drawText(String.valueOf(hour), x - fontSize*(hour<10 ? 0.28f : 0.6f), y + fontSize*0.355f, paint);
                    }
                }
            }
        }
        pinHourColor = Color.parseColor(source.stnn("pinHourColor"));
        pinMinColor = Color.parseColor(source.stnn("pinMinColor"));
        pinSecColor = Color.parseColor(source.stnn("pinSecColor"));
        var hhLen = (float) source.dbl("pinHourLen", 50);
        var mhLen = (float) source.dbl("pinMinLen", 75);
        var shLen = (float) source.dbl("pinSecLen", 100);
        var hhWidth = (float) source.dbl("pinHourWidth", 15);
        var mhWidth = (float) source.dbl("pinMinWidth", 10);
        var shWidth = (float) source.dbl("pinSecWidth", 5);
        showSecHand = source.bool("showSecond");

        var rx = hhWidth*sideLen/400;
        hPath = new Path();
        hPath.moveTo(rx, 0);
        hPath.lineTo(0, hhLen*sideLen/-200);
        hPath.lineTo(-rx, 0);
        hPath.close();

        rx = mhWidth*sideLen/400;
        mPath = new Path();
        mPath.moveTo(rx, 0);
        mPath.lineTo(0, mhLen*sideLen/-200);
        mPath.lineTo(-rx, 0);
        mPath.close();
        rx = shWidth*sideLen/400;
        sPath = new Path();
        sPath.moveTo(rx, 0);
        sPath.lineTo(0, shLen*sideLen/-200);
        sPath.lineTo(-rx, 0);
        sPath.close();
        prog.calls.add(this);
    }

    void cal() {
        //var time = timeZone==null ? LocalTime.now() : LocalTime.now(timeZone);
        calendar.setTimeInMillis(lastSec*1000);
        sAngle = calendar.get(Calendar.SECOND) * 6;
        mAngle = calendar.get(Calendar.MINUTE) * 6 + sAngle/60;
        hAngle = calendar.get(Calendar.HOUR_OF_DAY) * 30 + mAngle/12;
    }
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        if(img != null) canvas.drawBitmap(img, null, new RectF(0,0, getWidth(), getHeight()), null);
        canvas.translate(getWidth()/2f, getHeight()/2f);

        paintPin.setColor(pinHourColor);
        canvas.rotate(hAngle);
        canvas.drawPath(hPath, paintPin);

        paintPin.setColor(pinMinColor);
        canvas.rotate(mAngle-hAngle);
        canvas.drawPath(mPath, paintPin);
        if(showSecHand) {
            paintPin.setColor(pinSecColor);
            canvas.rotate(sAngle-mAngle);
            canvas.drawPath(sPath, paintPin);
        }
    }

    long lastSec;

    @Override
    public void doFrame(long ms) {
        if(! isShown()) return;
        var sec = ms / 1000;
        if(sec != lastSec) {
            lastSec = sec;
            cal();
            invalidate();
        }
    }
}