package com.xixun.xixunplayer;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.Choreographer;
import android.view.View;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

import gnph.util.JSList;
import gnph.util.JSMap;
import gnph.util.NumFmts;

@SuppressLint("ViewConstructor")
public class SrcEnviron extends View implements Choreographer.FrameCallback, IntentReceiver {
    static class Item {
        String key;
        Bitmap label;
        ArrayList<Bitmap> nums = new ArrayList<>();
        Bitmap unit;

        public Item(String key, Bitmap label, Bitmap unit) {
            this.key = key;
            this.label = label;
            this.unit = unit;
        }
    }
    static String[] directs = {"NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N"};
    HashMap<String, Bitmap> imgMap = new HashMap<>();
    Bitmap title;
    ArrayList<Item> items = new ArrayList<>();
    MainActivity act;
    int alignType, spaceWidth, digitHeight;
    int interval, cur, end, step;
    boolean isScroll, isFirst = true;

    public SrcEnviron(Prog prog, JSMap json) {
        super(prog.getContext());
        act = (MainActivity) prog.getContext();
        alignType = json.intg("alignType");
        spaceWidth = json.intg("spaceWidth");
        isScroll = json.bool("bSingleScroll");
        try {
            setBackgroundColor(Color.parseColor(json.stnn("backColor")));
        } catch (Exception ignored) {}
        var values = json.jsmap("values");
        if(values!=null) {
            if(values.get("0") instanceof String) {
                var titleStr = json.str("title");
                if(titleStr!=null) title = BitmapFactory.decodeFile(Util.programDir+"/"+titleStr);
                var entrys = values.entrySet();
                for(var entry : entrys) imgMap.put(entry.getKey(), BitmapFactory.decodeFile(Util.programDir+"/"+entry.getValue()));
                JSList<JSMap> jitems = json.jslist("items");
                for(var jitem : jitems) {
                    var unit = jitem.str("unit");
                    items.add(new Item(jitem.str("name"), BitmapFactory.decodeFile(Util.programDir + "/" + jitem.stnn("label")), unit == null ? null : BitmapFactory.decodeFile(Util.programDir + "/" + unit)));
                }
            } else {
                var big = BitmapFactory.decodeFile(Util.programDir+"/"+json.stnn("id"));
                var titleGeo = json.jsmap("title");
                if(titleGeo!=null) title = Bitmap.createBitmap(big, titleGeo.intg("x"), titleGeo.intg("y"), titleGeo.intg("w"), titleGeo.intg("h"));
                var entrys = values.entrySet();
                for(var entry : entrys) {
                    var val = (JSMap) entry.getValue();
                    imgMap.put(entry.getKey(), Bitmap.createBitmap(big, val.intg("x"), val.intg("y"), val.intg("w"), val.intg("h")));
                }
                JSList<JSMap> jitems = json.jslist("items");
                for(var jitem : jitems) {
                    var label = jitem.jsmap("label");
                    var unit = jitem.jsmap("unit");
                    items.add(new Item(jitem.str("name"), Bitmap.createBitmap(big, label.intg("x"), label.intg("y"), label.intg("w"), label.intg("h")), unit == null ? null : Bitmap.createBitmap(big, unit.intg("x"), unit.intg("y"), unit.intg("w"), unit.intg("h"))));
                }
            }
        } else {
            JSList<JSMap> pics = json.jslist("arrayPics");
            if(pics==null) return;
            if(! pics.isEmpty() && pics.get(0).containsKey("startX")) {
                var big = BitmapFactory.decodeFile(Util.programDir+"/"+json.stnn("id"));
                for(var pic : pics) {
                    var startX = pic.intg("startX");
                    var startY = pic.intg("startY");
                    imgMap.put(pic.str("name"), Bitmap.createBitmap(big, startX, startY, pic.intg("endX")-startX, pic.intg("endY")-startY));
                }
            } else for(var img : pics) imgMap.put(img.str("name"), BitmapFactory.decodeFile(Util.programDir+"/"+img.stnn("id")));
            imgMap.put("-", imgMap.remove("minus_sign"));
            title = imgMap.get("labeltitle");
            if(json.bool("bTemperature")) items.add(new Item("temperature", imgMap.remove("labeltemperature"), imgMap.remove("unit_celsius")));
            if(json.bool("bHumidity")) items.add(new Item("humidity", imgMap.remove("labelhumidity"), imgMap.remove("unit_humidity")));
            if(json.bool("bNoise")) items.add(new Item("noise", imgMap.remove("labelnoise"), imgMap.remove("unit_noise")));
            if(json.bool("bWindSpeed")) items.add(new Item("windSpeed", imgMap.remove("labelwindSpeed"), imgMap.remove("unit_windspeed")));
            if(json.bool("bWindDirection")) items.add(new Item("windDirection", imgMap.remove("labelwindDirection"), null));
            if(json.bool("bPM25")) items.add(new Item("pm2.5", imgMap.remove("labelpm25"), imgMap.get("unit_pm10")));
            if(json.bool("bPM10")) items.add(new Item("pm10", imgMap.remove("labelpm10"), imgMap.get("unit_pm10")));
        }
        digitHeight = imgMap.get("0").getHeight();
        if(spaceWidth==0) spaceWidth = imgMap.get("0").getWidth();
        var scrollSpeed = json.dbl("scrollSpeed");
        if(scrollSpeed==0) {
            var scrollDur = json.dbl("iScrollSpeed");
            if(scrollDur==0) return;
            scrollSpeed = 1000 / scrollDur;
        }
        interval = step = 1;
        if(scrollSpeed > 60) step = (int) Math.round(scrollSpeed/60);
        else if(scrollSpeed < 60) interval = (int) Math.round(60/scrollSpeed);
        if(isScroll) prog.calls.add(this);
    }

    public static Method method;
    static {
        try {
            method = Intent.class.getMethod("getExtra", String.class, Object.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void onReceive(Intent intent) {
        try {
            for(var item : items) {
                item.nums.clear();
                if(item.unit==null) {
                    var num = intent.getIntExtra(item.key, -1);
                    if(num>=0 && num<=15) {
                        if(directs[num].length() < 3) item.nums.add(imgMap.get(directs[num]));
                        else {
                            item.nums.add(imgMap.get(directs[num].substring(0, 1)));
                            item.nums.add(imgMap.get(directs[num].substring(1)));
                        }
                    } else {
                        var img = imgMap.get("-");
                        item.nums.add(img);
                        item.nums.add(img);
                    }
                } else {
                    var num = ((Number) method.invoke(intent, item.key, -999)).floatValue();
                    var str = num==-999 || (num==-1 && ! item.key.endsWith("rature")) ? "--" : NumFmts.zz().format(num);
                    for(int cc=0; cc<str.length(); cc++) item.nums.add(imgMap.get(str.substring(cc, cc+1)));
                }
            }
        } catch (Exception e) {
            Util.printStackTrace(e);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(isFirst) {
            isFirst = false;
            onReceive(act.environIntent);
            act.environs.add(this);
        }
        if(isScroll) {
            var x = cur;
            var cycCnt = cur==0 ? 1 : 2;
            for(int ccc=0; ccc<cycCnt; ccc++) {
                if(title!=null) {
                    canvas.drawBitmap(title, x, Math.round((getHeight() - title.getHeight()) / 2), null);
                    x += title.getWidth() + spaceWidth<<1;
                }
                var y = (int) Math.round((getHeight() - digitHeight) / 2);
                for(var item : items) {
                    if(item.label !=null) {
                        canvas.drawBitmap(item.label, x, y, null);
                        x += item.label.getWidth();
                    }
                    for(var num : item.nums) if(num!=null) {
                        canvas.drawBitmap(num, x, y, null);
                        x += num.getWidth();
                    }
                    if(item.unit!=null) {
                        canvas.drawBitmap(item.unit, x, y, null);
                        x += item.unit.getWidth();
                    }
                    x += spaceWidth<<1;
                }
                if(ccc==0) end = -(x-cur-step);
            }
        } else {
            var itemH = (double) getHeight() / (title!=null ? items.size()+1 : items.size());
            int i = 0, x = 0;
            if(title!=null) {
                if(alignType==1) x = (getWidth() - title.getWidth()) / 2;
                else if(alignType==2) x = getWidth() - title.getWidth();
                canvas.drawBitmap(title, x, Math.round(itemH * i++ + (itemH - title.getHeight()) / 2), null);
            }
            for(var item : items) {
                var y = (int) Math.round(itemH * i++ + (itemH - digitHeight) / 2);
                x = 0;
                if(alignType!=0) {
                    if(item.label !=null) x += item.label.getWidth();
                    for(var num : item.nums) if(num!=null) x += num.getWidth();
                    if(item.unit!=null) x += item.unit.getWidth();
                    x = getWidth() - x;
                    if(alignType==1) x /= 2;
                }
                if(item.label !=null) {
                    canvas.drawBitmap(item.label, x, y, null);
                    x += item.label.getWidth();
                }
                for(var num : item.nums) if(num!=null) {
                    canvas.drawBitmap(num, x, y, null);
                    x += num.getWidth();
                }
                if(item.unit!=null) canvas.drawBitmap(item.unit, x, y, null);
            }
        }
    }

    @Override
    public void onVisibilityAggregated(boolean isVisible) {
        super.onVisibilityAggregated(isVisible);
        if(! isVisible) {
            act.environs.remove(this);
            isFirst = true;
        }
    }

    int freshCnt;

    @Override
    public void doFrame(long ms) {
        if(! isShown()) {
            freshCnt = cur = 0;
            return;
        }
        if(freshCnt < interval) freshCnt++;
        else {
            freshCnt = 1;
            if(cur <= end) cur -= end;
            else cur -= step;
            invalidate();
        }
    }
}
