package com.rv.rvmine.view;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.text.TextUtils;
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.Toast;

import com.rv.component.utils.DisplayUtil;
import com.rv.rvmine.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.util.Date;

public class DateTimeWheelDialog extends Dialog {

    public static final int SHOW_YEAR = 0;
    public static final int SHOW_YEAR_MONTH = 1;
    public static final int SHOW_YEAR_MONTH_DAY = 2;
    public static final int SHOW_YEAR_MONTH_DAY_HOUR = 3;
    public static final int SHOW_YEAR_MONTH_DAY_HOUR_MINUTE = 4;

    @IntDef({
            SHOW_YEAR,
            SHOW_YEAR_MONTH,
            SHOW_YEAR_MONTH_DAY,
            SHOW_YEAR_MONTH_DAY_HOUR,
            SHOW_YEAR_MONTH_DAY_HOUR_MINUTE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ShowConfig {
    }

    private final int MIN_MONTH = 1;
    private final int MAX_MONTH = 12;

    private WheelItemView yearWheelItemView;
    private WheelItemView monthWheelItemView;

    private DateItem[] yearItems;
    private DateItem[] monthItems;

    private Button btnConfirm;

    private Calendar startCalendar = Calendar.getInstance();
    private Calendar endCalendar = Calendar.getInstance();
    private Calendar selectedCalendar = Calendar.getInstance();

    private int showCount = 3;
    private int itemVerticalSpace = 30;
    private boolean isViewInitialized = false;
    private boolean keepLastSelected = false;
    private int showConfig = SHOW_YEAR_MONTH_DAY_HOUR_MINUTE;

    public DateTimeWheelDialog(@NonNull Context context) {
        this(context, R.style.WheelDialog);
    }

    private DateTimeWheelDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        if (getWindow() != null) {
            getWindow().setGravity(Gravity.CENTER);
            getWindow().setBackgroundDrawable(null);
            getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT);
        }
        setContentView(R.layout.wheel_dialog_base);
        initView();
    }

    private void initView() {
        isViewInitialized = true;
        LinearLayout lyPickerContainer = findViewById(R.id.wheel_id_picker_container);
        //year
        yearWheelItemView = new WheelItemView(lyPickerContainer.getContext());
        yearWheelItemView.setItemVerticalSpace(DisplayUtil.dip2px(getContext(), itemVerticalSpace));
        yearWheelItemView.setShowCount(showCount);
        lyPickerContainer.addView(yearWheelItemView, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1));
        //month
        monthWheelItemView = new WheelItemView(lyPickerContainer.getContext());
        monthWheelItemView.setItemVerticalSpace(DisplayUtil.dip2px(getContext(), itemVerticalSpace));
        monthWheelItemView.setShowCount(showCount);
        lyPickerContainer.addView(monthWheelItemView, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1));

        btnConfirm = findViewById(R.id.btn_confirm);
        btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener == null) {
                    dismiss();
                    return;
                }
                if (isScrolling()) {
                    return;
                }
                mListener.callBack(v, selectedCalendar.get(Calendar.YEAR), selectedCalendar.get(Calendar.MONTH) + 1);
                dismiss();
            }
        });
    }

    @Override
    public void show() {
        super.show();
        if (getWindow() != null) {
            getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
    }

    private OnClickCallBack mListener;

    public void setOkListener(OnClickCallBack listener) {
        this.mListener = listener;
    }

    public void configShowUI(@ShowConfig int config) {
        configShowUI(config, -1);
    }

    public void configShowUI(@ShowConfig int showConfig, int totalOffsetX) {
        ensureIsViewInitialized();
        this.showConfig = showConfig;
        yearWheelItemView.setTotalOffsetX(0);
        monthWheelItemView.setTotalOffsetX(0);

        yearWheelItemView.setVisibility(View.VISIBLE);
        monthWheelItemView.setVisibility(View.VISIBLE);
    }

    public void setDateArea(@NonNull Date startDate, @NonNull Date endDate, boolean keepLastSelected) {
        ensureIsViewInitialized();
        if (startDate.after(endDate))
            throw new IllegalArgumentException("start date should be before end date");
        startCalendar.setTime(startDate);
        endCalendar.setTime(endDate);
        selectedCalendar.setTimeInMillis(startDate.getTime());
        this.keepLastSelected = keepLastSelected;
        initAreaDate();
    }

    public void updateSelectedDate(@NonNull Date selectedDate) {
        ensureIsViewInitialized();
        if (selectedDate.before(startCalendar.getTime()) || selectedDate.after(endCalendar.getTime()))
            throw new IllegalArgumentException("selected date must be between start date and end date");
        selectedCalendar.setTime(selectedDate);
        initSelectedDate();
        initOnScrollListener();
    }

    public void updateSelectedDate(String date) {
        ensureIsViewInitialized();
        Date selectedDate = dateChange(date);
        if (selectedDate.before(startCalendar.getTime()) || selectedDate.after(endCalendar.getTime()))
            throw new IllegalArgumentException("selected date must be between start date and end date");
        selectedCalendar.setTime(selectedDate);
        initSelectedDate();
        initOnScrollListener();
    }

    private Date dateChange(String date) {
        try {
            if (!TextUtils.isEmpty(date)) {
                String[] split = date.split("-");
                if (split.length >= 2) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.YEAR, Integer.valueOf(split[0]));
                    calendar.set(Calendar.MONTH, Integer.valueOf(split[1]) - 1);
                    calendar.set(Calendar.DAY_OF_MONTH, 1);
                    calendar.set(Calendar.HOUR_OF_DAY, 0);
                    calendar.set(Calendar.MINUTE, 0);
                    return calendar.getTime();
                } else {
                    return new Date();
                }
            } else {
                return new Date();
            }
        } catch (Exception e) {
            return new Date();
        }
    }

    private void initAreaDate() {
        int startYear = startCalendar.get(Calendar.YEAR);
        int endYear = endCalendar.get(Calendar.YEAR);
        int startMonth = startCalendar.get(Calendar.MONTH) + 1;

        yearItems = updateItems(DateItem.TYPE_YEAR, startYear, endYear);
        monthItems = updateItems(DateItem.TYPE_MONTH, startMonth, MAX_MONTH);
        yearWheelItemView.setItems(yearItems);
        monthWheelItemView.setItems(monthItems);
    }

    private void initOnScrollListener() {
        yearWheelItemView.setOnSelectedListener(new WheelView.OnSelectedListener() {
            @Override
            public void onSelected(Context context, int selectedIndex) {
                selectedCalendar.set(Calendar.YEAR, yearItems[selectedIndex].getValue());
                if (showConfig > SHOW_YEAR)
                    onYearChanged();
            }
        });
        monthWheelItemView.setOnSelectedListener(new WheelView.OnSelectedListener() {
            @Override
            public void onSelected(Context context, int selectedIndex) {
                selectedCalendar.set(Calendar.MONTH, monthItems[selectedIndex].getValue() - 1);
            }
        });
    }

    private void initSelectedDate() {
        int year = selectedCalendar.get(Calendar.YEAR);
        int month = selectedCalendar.get(Calendar.MONTH) + 1;
        int index = findSelectedIndexByValue(yearItems, year);
        yearWheelItemView.setSelectedIndex(index, false);
        index = findSelectedIndexByValue(monthItems, month);
        monthWheelItemView.setSelectedIndex(index, false);
    }

    private void onYearChanged() {
//        //update month list
//        int startYear = startCalendar.get(Calendar.YEAR);
//        int endYear = endCalendar.get(Calendar.YEAR);
//        int selectedYear = selectedCalendar.get(Calendar.YEAR);
//        int startMonth = startCalendar.get(Calendar.MONTH) + 1;
//        int endMonth = endCalendar.get(Calendar.MONTH) + 1;
//        int selectedMonth = selectedCalendar.get(Calendar.MONTH) + 1;
//        int tempIndex = -1;
//        int lastSelectedIndex = -1;
//        int startValue, endValue;
//        if (isSameValue(selectedYear, startYear)) {
//            startValue = startMonth;
//            endValue = MAX_MONTH;
//        } else if (isSameValue(selectedYear, endYear)) {
//            startValue = MIN_MONTH;
//            endValue = endMonth;
//        } else {
//            startValue = MIN_MONTH;
//            endValue = MAX_MONTH;
//        }
//        monthItems = new DateItem[endValue - startValue + 1];
//        for (int i = startValue; i <= endValue; i++) {
//            tempIndex++;
//            monthItems[tempIndex] = new DateItem(DateItem.TYPE_MONTH, i);
//            if (isSameValue(selectedMonth, i)) {
//                lastSelectedIndex = tempIndex;
//            }
//        }
//        int newSelectedIndex = keepLastSelected ? (lastSelectedIndex == -1 ? 0 : lastSelectedIndex) : 0;
//        monthWheelItemView.setItems(monthItems);
//        monthWheelItemView.setSelectedIndex(newSelectedIndex);
    }


    private int findSelectedIndexByValue(DateItem[] items, int value) {
        int selectedIndex = 0;
        for (int i = 0; i < items.length; i++) {
            if (isSameValue(value, items[i].getValue())) {
                selectedIndex = i;
                break;
            }
        }
        return selectedIndex;
    }

    private DateItem[] updateItems(@DateItem.DateType int type, int startValue, int endValue) {
        int index = -1;
        DateItem[] items = new DateItem[endValue - startValue + 1];
        for (int i = startValue; i <= endValue; i++) {
            index++;
            items[index] = new DateItem(type, i);
        }
        return items;
    }

    private boolean isScrolling() {
        return yearWheelItemView.isScrolling()
                || monthWheelItemView.isScrolling();
    }

    private boolean isSameValue(int value1, int value2) {
        return value1 == value2;
    }

    private void ensureIsViewInitialized() {
        if (!isViewInitialized)
            throw new IllegalStateException("View wasn't initialized, call show() first.");
    }

    public interface OnClickCallBack {
        boolean callBack(View v, int year, int month);
    }
}
