package com.axzae.homeassistant.fragment.control;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.axzae.homeassistant.R;
import com.axzae.homeassistant.model.Entity;
import com.axzae.homeassistant.model.HomeAssistantServer;
import com.axzae.homeassistant.model.rest.CallServiceRequest;
import com.axzae.homeassistant.provider.ServiceProvider;
import com.axzae.homeassistant.util.CommonUtil;
import com.axzae.homeassistant.util.FaultUtil;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.view.LineChartView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class ClimateFragment extends BaseControlFragment implements View.OnClickListener {

    private Call<ArrayList<ArrayList<Entity>>> mCall;
    private View mProgressBar;
    private HomeAssistantServer mServer;
    private LineChartView mChart;
    private ViewGroup mEmptyView;
    private ViewGroup mConnErrorView;
    private TextView mTargetState;
    private TextView mCurrentState;

    public static ClimateFragment newInstance(Entity entity, HomeAssistantServer server) {
        ClimateFragment fragment = new ClimateFragment();
        Bundle args = new Bundle();
        args.putString("entity", CommonUtil.deflate(entity));
        args.putString("server", CommonUtil.deflate(server));
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mServer = CommonUtil.inflate(getArguments().getString("server"), HomeAssistantServer.class);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View rootView = getActivity().getLayoutInflater().inflate(R.layout.control_climate, null);
        builder.setView(rootView);
        builder.setTitle(mEntity.getFriendlyName());

        mChart = rootView.findViewById(R.id.chart);
        mTargetState = rootView.findViewById(R.id.text_target_state);
        mCurrentState = rootView.findViewById(R.id.text_current_temperature);
        mEmptyView = rootView.findViewById(R.id.list_empty);
        mConnErrorView = rootView.findViewById(R.id.list_conn_error);

        rootView.findViewById(R.id.text_minus).setOnClickListener(this);
        rootView.findViewById(R.id.text_plus).setOnClickListener(this);
        mProgressBar = rootView.findViewById(R.id.progressbar);
        callService();
        refreshUi();

        return builder.create();
    }

    public void callService() {
        if (mCall == null) {
            mProgressBar.setVisibility(View.VISIBLE);
            mCall = ServiceProvider.getApiService(mServer.getBaseUrl()).getHistory(mServer.getPassword(), mEntity.entityId);
            mCall.enqueue(new Callback<ArrayList<ArrayList<Entity>>>() {
                @Override
                public void onResponse(@NonNull Call<ArrayList<ArrayList<Entity>>> call, @NonNull Response<ArrayList<ArrayList<Entity>>> response) {
                    mCall = null;
                    mProgressBar.setVisibility(View.GONE);

                    if (FaultUtil.isRetrofitServerError(response)) {
                        Log.d("YouQi", response.message());
//                        showError(response.message());
                        return;
                    }

                    ArrayList<ArrayList<Entity>> restResponse = response.body();
                    CommonUtil.logLargeString("YouQi", "HISTORY restResponse: " + CommonUtil.deflate(restResponse));

                    if (restResponse != null && restResponse.size() > 0) {
                        ArrayList<Entity> histories = restResponse.get(0);
                        if (histories.size() <= 1) {
                            mEmptyView.setVisibility(View.VISIBLE);
                        } else {
                            setupChart(histories);
                        }
                    } else {
                        mEmptyView.setVisibility(View.VISIBLE);
                    }


                }

                @Override
                public void onFailure(@NonNull Call<ArrayList<ArrayList<Entity>>> call, @NonNull Throwable t) {
                    mCall = null;
                    mProgressBar.setVisibility(View.GONE);

                    t.printStackTrace();
                    mConnErrorView.setVisibility(View.VISIBLE);
                    Log.d("YouQi", FaultUtil.getPrintableMessage(getActivity(), t));
//                    showError(FaultUtil.getPrintableMessage(t));
                }
            });
        }


        //ContentValues values = new ContentValues();
        //values.put(HabitTable.TIME); //whatever column you want to update, I dont know the name of it
        //getContentResolver().update(HabitTable.CONTENT_URI,values,HabitTable.ID+"=?",new String[] {String.valueOf(id)}); //id is the id of the row you wan to update
        //getContentResolver().update()
    }

    private class DataItem {
        public SimpleDateFormat df = new SimpleDateFormat("MMM-dd HH:mm", Locale.ENGLISH);
        public Date date;
        public Float value;

        DataItem(Date date, Float value) {
            this.date = date;
            this.value = value;
        }

        public String getLabel() {
            return df.format(date);
        }

        public long getXValue() {
            return date.getTime();
        }

        public Float getYValue() {
            return value;
        }
    }

    private void setupChart(ArrayList<Entity> histories) {

        DateFormat df = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ", Locale.ENGLISH));
        ArrayList<DataItem> mDataCurrent = new ArrayList<>();
        ArrayList<DataItem> mDataTarget = new ArrayList<>();
        for (Entity history : histories) {
            try {
                if (history.attributes.currentTemperature != null) {
                    mDataCurrent.add(new DataItem(df.parse(history.lastUpdated), history.attributes.currentTemperature.floatValue()));
                }

                mDataTarget.add(new DataItem(df.parse(history.lastUpdated), history.attributes.getTemperature().floatValue()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Line currentLine = getLine(mDataCurrent, "#3366cc");
        Line targetLine = getLine(mDataTarget, "#dc3912");

        List<PointValue> yValues = new ArrayList<>();
        List<AxisValue> axisValues = new ArrayList<>();
        for (int x = 0; x < mDataTarget.size(); ++x) {
            DataItem dataItem = mDataTarget.get(x);
            float yValue = dataItem.getYValue();
            yValues.add(new PointValue(dataItem.getXValue(), yValue));
        }

        //In most cased you can call data model methods in builder-pattern-like manner.
        List<Line> lines = new ArrayList<>();
        lines.add(currentLine);
        lines.add(targetLine);

        LineChartData data = new LineChartData();
        data.setLines(lines);

        Axis axisY = new Axis().setHasLines(true);
        axisY.setName(mEntity.attributes.unitOfMeasurement);
        data.setAxisYLeft(axisY);

        Axis axisX;

        if (mDataCurrent.size() != 0) {
            axisX = getXAxis(mDataCurrent);
        } else if (mDataTarget.size() != 0) {
            axisX = getXAxis(mDataTarget);
        } else {
            axisX = new Axis().setName("Time (Last 24 Hours)");
        }

        data.setAxisXBottom(axisX);

        mChart.setLineChartData(data);
        mChart.setVisibility(View.VISIBLE);
    }

    private Axis getXAxis(ArrayList<DataItem> data) {
        long startTime = data.get(0).getXValue();
        long endTime = data.get(data.size() - 1).getXValue();
        long step = (endTime - startTime) / 10;
        List<AxisValue> xValues = new ArrayList<>();
        SimpleDateFormat df2 = new SimpleDateFormat("HH:mm", Locale.ENGLISH);

        for (long i = startTime; i < endTime; i += step) {
            xValues.add(new AxisValue(i).setLabel(df2.format(new Date(i))));
        }
        xValues.add(new AxisValue(endTime).setLabel(df2.format(new Date(endTime))));
        Axis axisX = new Axis(xValues);
        axisX.setName("Time (Last 24 Hours)");
        return axisX;
    }

    private Line getLine(ArrayList<DataItem> dataItems, String color) {

        List<PointValue> values = new ArrayList<>();
        for (int x = 0; x < dataItems.size(); ++x) {
            DataItem dataItemCurrent = dataItems.get(x);
            values.add(new PointValue(dataItemCurrent.getXValue(), dataItemCurrent.getYValue()));
        }

        return new Line(values).setColor(Color.parseColor(color)).setCubic(false).setHasLabels(true).setHasPoints(false).setCubic(false);
    }

    private void refreshUi() {

        if (mEntity.attributes.getTemperature() != null) {
            String result = String.format(Locale.ENGLISH, "%s %s", mEntity.attributes.getTemperature().setScale(1, BigDecimal.ROUND_UP).toString(), mEntity.attributes.unitOfMeasurement);
            mTargetState.setText(result);
            mTargetState.setVisibility(View.VISIBLE);
        } else {
            mTargetState.setVisibility(View.GONE);
        }

        if (mEntity.attributes.currentTemperature != null) {
            String currentState = String.format(Locale.ENGLISH, "%s %s", mEntity.attributes.currentTemperature.setScale(1, BigDecimal.ROUND_UP).toString(), mEntity.attributes.unitOfMeasurement);
            mCurrentState.setText(currentState);
            mCurrentState.setVisibility(View.VISIBLE);
        } else {
            mCurrentState.setVisibility(View.GONE);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button_cancel:
                dismiss();
                break;

            case R.id.button_set:
                dismiss();
                break;

            case R.id.text_minus:
                callService("climate", "set_temperature", new CallServiceRequest(mEntity.entityId).setTemperature(mEntity.attributes.getTemperature().subtract(new BigDecimal(0.5))));
                break;

            case R.id.text_plus:
                callService("climate", "set_temperature", new CallServiceRequest(mEntity.entityId).setTemperature(mEntity.attributes.getTemperature().add(new BigDecimal(0.5))));
                break;
        }
    }

    @Override
    public void onChange(Entity entity) {
        super.onChange(entity);
        refreshUi();
    }

}