package com.tsi.navi.activity.fragment;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.tsi.navi.R;
import com.tsi.navi.TsiNaviApplication;
import com.tsi.navi.activity.model.CpuControl;
import com.tsi.navi.activity.model.SignalItem;
import com.tsi.navi.dto.CpuNodeStatusDTO;
import com.tsi.navi.util.TsiUtils;
import com.tsi.navi.vo.NodeVo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class DirectionNaviSignalFragment extends Fragment {
    private static final String TAG = DirectionNaviSignalFragment.class.getSimpleName();

    private Context context;

    private NodeVo node;
    private long nodeId;
    private CpuControl cpuControl;

    private TextView tvCycle;

    private ImageView[] imgSignal = new ImageView[4];

    private int directionCode;
    private boolean first;
    private Set<String> directions = new HashSet();

    private final  int MAX_SIGNAL = 4;
    private int[] sigIdx = new int[MAX_SIGNAL];

    private int[][] signalId = {
            {   // RED
                    R.drawable.ic_sig_off,
                    R.drawable.ic_sig_red,
            },
            {   // YELLOW
                    R.drawable.ic_sig_off,
                    R.drawable.ic_sig_yellow,
            },
            {   // LEFT
                    R.drawable.ic_sig_left_off,
                    R.drawable.ic_sig_left_on,
            },
            {   // STRAIGHT
                    R.drawable.ic_sig_off,
                    R.drawable.ic_sig_green,
            },
    };
    private int[][] signalIdUn = {
            {   // none
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
                    R.drawable.rect_none,                  // 데이터 없음.
            },
            {   // 직진
                    R.drawable.ic_signal_straight_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_straight_red_un,      // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_straight_yellow_un,   // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_straight_green_un,    // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_straight_red_un,      // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_straight_yellow_un,   // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_straight_green_un,    // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 좌회전
                    R.drawable.ic_signal_left_off_un,          // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_left_red_un,          // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_left_yellow_un,       // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_left_green_un,        // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_left_red_un,          // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_left_yellow_un,       // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_left_green_un,        // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 보행자
                    R.drawable.ic_signal_walk_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_walk_red_un,        // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_walk_yellow_un,     // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_walk_green_un,         // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_walk_red_un,        // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_walk_yellow_un,     // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_walk_green_un,         // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 자전거
                    R.drawable.ic_signal_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_red_un,            // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_yellow_un,         // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_green_un,       // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_red_un,            // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_yellow_un,         // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_green_un,       // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 우회전
                    R.drawable.ic_signal_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_red_un,            // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_yellow_un,         // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_green_un,       // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_red_un,            // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_yellow_un,         // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_green_un,       // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 버스
                    R.drawable.ic_signal_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_red_un,            // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_yellow_un,         // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_green_un,       // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_red_un,            // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_yellow_un,         // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_green_un,       // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
            {   // 유턴
                    R.drawable.ic_signal_uturn_off_un,      // LIGHTS_OUT   (0, "LIGHTS_OUT"),     //소등
                    R.drawable.ic_signal_uturn_red_un,            // RED_SOLID    (1, "RED_SOLID"),      //적색점등
                    R.drawable.ic_signal_uturn_yellow_un,         // YELLOW_SOLID (2, "YELLOW_SOLID"),   //황색점등
                    R.drawable.ic_signal_uturn_green_un,       // GREEN_SOLID  (3, "GREEN_SOLID"),    //녹색점등
                    R.drawable.ic_signal_uturn_red_un,            // RED_BLINK    (4, "RED_BLINK"),      //적색점멸
                    R.drawable.ic_signal_uturn_yellow_un,         // YELLOW_BLINK (5, "YELLOW_BLINK"),   //황색점멸
                    R.drawable.ic_signal_uturn_green_un,       // GREEN_BLINK  (6, "GREEN_BLINK");    //녹색점멸
                    R.drawable.rect_none,                   // 데이터 없음.
            },
    };

    private SignalItem signalCurr = null;
    private SignalItem signalPrev = null;

    // 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6)
    // 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7)

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_direction_navi_signal, container, false);

        this.tvCycle = v.findViewById(R.id.tv_cycle);
        this.tvCycle.setOnClickListener(view -> {
            if (this.directions.size() == 0) {
                return;
            }
            Log.e("Direction", this.directions.toString());
            List<String> directionList = new ArrayList(this.directions);
            Collections.sort(directionList);
            String[] dirs = new String[directionList.size()];
            for(int ii = 0; ii  < directionList.size(); ii++) {
                dirs[ii] = TsiNaviApplication.getDirection().getName(Integer.parseInt(directionList.get(ii)));
            }
            Log.e("Direction", dirs.toString());

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("방향코드 선택");
            builder.setItems(dirs, (dialog, which) -> {
                int selDirection = TsiNaviApplication.getDirection().getNameCode(dirs[which]);
                if (selDirection != directionCode) {
                    initStatus();
                    setDirectionCode(selDirection);
                }
                }
            );
            builder.show();
        });

        this.imgSignal[0] = (ImageView) v.findViewById(R.id.img_red);
        this.imgSignal[1] = (ImageView) v.findViewById(R.id.img_yellow);
        this.imgSignal[2] = (ImageView) v.findViewById(R.id.img_left);
        this.imgSignal[3] = (ImageView) v.findViewById(R.id.img_straight);

        this.first = false;
        this.directionCode = 0;

        if (this.signalCurr == null) {
            this.signalCurr = new SignalItem();
        }
        if (this.signalPrev == null) {
            this.signalPrev = new SignalItem();
        }

        this.cpuControl = new CpuControl();
        this.nodeId = 0;

        init(0);

        return v;
    }

    protected void setDirectionCode(int directionCode) {
        this.directionCode = directionCode;
        String name = TsiNaviApplication.getDirection().getName(this.directionCode);
        this.signalCurr.setDirection(this.directionCode);
        this.signalPrev.setDirection(this.directionCode);
    }

    protected void init(int directionCode) {
        if (this.node != null) {
            this.nodeId = this.node.getNodeId();
        }
        else {
            this.nodeId = 0;
        }

        initStatus();
        setDirectionCode(directionCode);
    }
    @SuppressLint("ObsoleteSdkInt")
    public void initStatus() {
        this.cpuControl.init();

        for (int ii = 0; ii < this.MAX_SIGNAL; ii++) {
            if (this.imgSignal[ii] != null) {
                if (this.imgSignal[ii].getAnimation() != null) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                        this.imgSignal[ii].getAnimation().cancel();
                    }
                    this.imgSignal[ii].clearAnimation();
                    this.imgSignal[ii].setAnimation(null);
                }
                this.imgSignal[ii].setImageResource(signalId[ii][0]);
            }
        }

        this.signalCurr.initStatus();
        this.signalPrev.initStatus();
    }
    public long getNodeId() {
        return this.nodeId;
    }

    public void setNodeCross(NodeVo node, int directionCode) {
        this.first = true;
        this.node = node;
        init(directionCode);
    }

    @SuppressLint("ObsoleteSdkInt")
    public void updateSignal(CpuNodeStatusDTO status) {
        if (this.node == null || this.nodeId != status.getA()) {
            return;
        }

        if (this.first) {
            this.directions.clear();
            int directionCode = this.directionCode;
            for (int ii = 0; ii < status.getG().size(); ii++) {
                this.directions.add(String.valueOf(status.getG().get(ii).getH()));
                if (ii == 0) {
                    directionCode = status.getG().get(ii).getH();
                }
                if (this.directionCode == status.getG().get(ii).getH()) {
                    directionCode = this.directionCode;
                }
            }
            // 프로그램에서 설정한 방향코드가 수집한 상태정보의 방향코드에 존재하지 않으면 첫번째 방향코드로 변경한다.
            if (this.directionCode != directionCode) {
                setDirectionCode(directionCode);
            }

            this.first = false;
        }

        this.cpuControl.updateStatus(status.getD());
        // 방향코드에 맞는 데이터 표출
        for (int ii = 0; ii < status.getG().size(); ii++) {
            if (status.getG().get(ii).getH() == this.directionCode) {
                this.signalCurr.setStatus(status.getG().get(ii));
            }
        }

        int lightStatus;
        int remainSeconds;

        for (int ii = 0; ii < this.MAX_SIGNAL; ii++) {
            this.sigIdx[ii] = 0;
        }
        boolean isBlink = false;
        remainSeconds = this.signalCurr.getRemainTime(TsiUtils.SIGNAL_STRAIGHT);
        lightStatus = this.signalCurr.getLightStatus(TsiUtils.SIGNAL_STRAIGHT);
        switch (lightStatus) {
            case 0: // light out
                break;
            case 1: // red solid
                this.sigIdx[0] = 1;
                break;
            case 4: // red blink
                this.sigIdx[0] = 1;
                isBlink = true;
                break;
            case 2: // yellow solid
                this.sigIdx[1] = 1;
                break;
            case 5: // yellow blink
                this.sigIdx[1] = 1;
                isBlink = true;
                break;
            case 3: // green solid
                this.sigIdx[3] = 1;
                break;
            case 6: // green blink
                this.sigIdx[3] = 1;
                isBlink = true;
                break;
        }
        lightStatus = this.signalCurr.getLightStatus(TsiUtils.SIGNAL_LEFT_TURN);
        switch (lightStatus) {
            case 0: // light out
                break;
            case 1: // red solid
                this.sigIdx[0] = 1;
                break;
            case 4: // red blink
                this.sigIdx[0] = 1;
                isBlink = true;
                break;
            case 2: // yellow solid
                this.sigIdx[1] = 1;
                break;
            case 5: // yellow blink
                this.sigIdx[1] = 1;
                isBlink = true;
                break;
            case 3: // green solid
                this.sigIdx[2] = 1;
                break;
            case 6: // green blink
                this.sigIdx[2] = 1;
                isBlink = true;
                break;
        }
        if (lightStatus == 2 || lightStatus == 5) {
            // YELLOW 일때
            if (this.sigIdx[0] == 1) {
                remainSeconds = this.signalCurr.getRemainTime(TsiUtils.SIGNAL_LEFT_TURN);
            }
        }
        if (this.sigIdx[2] == 1 && this.sigIdx[0] == 1) {
            // 좌회전, 레드가 모구 켜져있으면 좌회전 신호 표출
            this.sigIdx[0] = 0;
            remainSeconds = this.signalCurr.getRemainTime(TsiUtils.SIGNAL_LEFT_TURN);
        }
        if (this.sigIdx[1] == 1 && this.sigIdx[0] == 1) {
            // 레드, 옐로우 켜져 있으면 옐로우 신호 표출
            this.sigIdx[0] = 0;
        }

        if (remainSeconds < 0) remainSeconds = 255;
        this.tvCycle.setText(" " +String.valueOf(remainSeconds));
        for (int ii = 0; ii < this.MAX_SIGNAL; ii++) {
            if (this.imgSignal[ii].getAnimation() != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    this.imgSignal[ii].getAnimation().cancel();
                }
                this.imgSignal[ii].clearAnimation();
                this.imgSignal[ii].setAnimation(null);
            }
            this.imgSignal[ii].setImageResource(signalId[ii][this.sigIdx[ii]]);
            if (isBlink && this.sigIdx[ii] == 1) {
                Animation animation = AnimationUtils.loadAnimation(this.context, R.anim.blink);
                this.imgSignal[ii].startAnimation(animation);
            }
        }
    }
}
