package com.jachdev.consumerprotection.ui.exercise;

import androidx.core.app.ActivityCompat;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import butterknife.BindView;
import butterknife.OnClick;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.jachdev.commonlibs.base.BaseActivity;
import com.jachdev.commonlibs.validator.Validator;
import com.jachdev.commonlibs.widget.CustomEditText;
import com.jachdev.commonlibs.widget.CustomTextView;
import com.jachdev.consumerprotection.R;
import com.jachdev.consumerprotection.data.Health;
import com.jachdev.consumerprotection.ui.calories.PedometerActivity;
import com.jachdev.consumerprotection.ui.calories.ExercisesSuggeserActivity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class ExercisePlanActivity extends BaseActivity {

    private static final String TAG = ExercisePlanActivity.class.getSimpleName();
    private ExerciseViewModel exerciseViewModel;

    @BindView(R.id.et_weight)
    CustomEditText etWeight;
    @BindView(R.id.et_height)
    CustomEditText etHeight;

    @BindView(R.id.chart)
    BarChart chart;
    @BindView(R.id.tvXAxisLabel)
    CustomTextView tvXAxisLabel;
    @BindView(R.id.tvYAxisLabel)
    CustomTextView tvYAxisLabel;

    private List<Health> health;

    private double weight, height = 0;

    @Override
    protected int layoutRes() {
        return R.layout.activity_exercise_plan;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        exerciseViewModel = new ViewModelProvider(this).get(ExerciseViewModel.class);

        observeViewModels();
        init();
        getData();
    }

    @OnClick(R.id.btnExercises)
    void onExercisesClick(){

        Intent intent = new Intent(ExercisePlanActivity.this, ExercisesActivity.class);

        Bundle bundle = new Bundle();
        bundle.putDouble(PedometerActivity.KEY_DATA_WEIGHT, weight);
        bundle.putDouble(PedometerActivity.KEY_DATA_HEIGHT, height);

        intent.putExtras(bundle);

        startActivity(intent);
    }

    @OnClick(R.id.btnPedometer)
    void onPedometerClick(){

        Intent intent = new Intent(ExercisePlanActivity.this, PedometerActivity.class);

        Bundle bundle = new Bundle();
        bundle.putDouble(PedometerActivity.KEY_DATA_WEIGHT, weight);
        bundle.putDouble(PedometerActivity.KEY_DATA_HEIGHT, height);

        intent.putExtras(bundle);

        startActivity(intent);
    }

    @OnClick(R.id.btnSave)
    void onSaveClick(){
        if(!Validator.isValidField(etWeight) || !Validator.isValidField(etHeight)){
            return;
        }

        double weight = etWeight.getTextDouble();
        double height = etHeight.getTextDouble();

        if(height >= 400){
            etHeight.setError(getString(R.string.cl_error_input_valid_field));

            return;
        }

        if(weight >= 1000){
            etWeight.setError(getString(R.string.cl_error_input_valid_field));

            return;
        }

        exerciseViewModel.addHealth(height, weight);
    }

    private void observeViewModels() {
        exerciseViewModel.getHealthData().observe(ExercisePlanActivity.this, new Observer<List<Health>>() {
            @Override
            public void onChanged(List<Health> health) {

                if (health == null)
                    return;

                ExercisePlanActivity.this.health = health;

                Health h = health.get(health.size() - 1);

                weight = h.getWeight();
                height = h.getHeight();

                etHeight.setAnyText(String.valueOf(weight));
                etWeight.setAnyText(String.valueOf(height));

                setXYAxis();
                drawDiagram();
            }
        });
    }

    private void init() {
    }

    private void getData() {
        exerciseViewModel.getHealth();
    }

    private void setXYAxis() {
        tvXAxisLabel.setAnyText("BMI");

        String yLabel = "Time";
        tvYAxisLabel.setAnyText(yLabel);

        //hiding the grey background of the chart, default false if not set
        chart.setDrawGridBackground(false);
        //remove the bar shadow, default false if not set
        chart.setDrawBarShadow(false);
        //remove border of the chart, default false if not set
        chart.setDrawBorders(false);

        //remove the description label text located at the lower right corner
        Description description = new Description();
        description.setEnabled(false);
        chart.setDescription(description);

        //setting animation for y-axis, the bar will pop up from 0 to its value within the time we set
        chart.animateY(500);
        //setting animation for x-axis, the bar will pop up separately within the time we set
        chart.animateX(500);

        XAxis xAxis = chart.getXAxis();
        //change the position of x-axis to the bottom
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        //set the horizontal distance of the grid line
        xAxis.setGranularity(1f);
        //hiding the x-axis line, default true if not set
        xAxis.setDrawAxisLine(false);
        //hiding the vertical grid lines, default true if not set
        xAxis.setDrawGridLines(false);

        YAxis leftAxis = chart.getAxisLeft();
        //hiding the left y-axis line, default true if not set
        leftAxis.setDrawAxisLine(true);

        YAxis rightAxis = chart.getAxisRight();
        //hiding the right y-axis line, default true if not set
        rightAxis.setDrawAxisLine(false);

        Legend legend = chart.getLegend();
        //setting the shape of the legend form to line, default square shape
        legend.setForm(Legend.LegendForm.LINE);
        //setting the text size of the legend
        legend.setTextSize(8f);
        //setting the alignment of legend toward the chart
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
        legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        //setting the stacking direction of legend
        legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        //setting the location of legend outside the chart, default false if not set
        legend.setDrawInside(false);
    }

    private void drawDiagram() {
        List<BarEntry> entries = new ArrayList<BarEntry>();
        List<Integer> colors = new ArrayList<Integer>();
        int max = 0;
        int min = 0;

        if(health == null)
            return;

        for (int x = 0; x < health.size(); x++) {
            Health d = health.get(x);
            long date = d.getTimestamp();
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(date*1000);
            int value = 0;

            double h = d.getHeight()/100;
            double w = d.getWeight();

            double bmi = w/(h*h);

            value = (int) bmi;

            Log.d(TAG, "bmi: " + value);

//            switch (testReportType){
//                case GLUCOSE:
//                    value = (int) Double.parseDouble(d.getGlu());
//                    break;
//                case CHOLESTEROL:
//                    value = (int) Double.parseDouble(d.getCho());
//                    break;
//                case HDL:
//                    value = (int) Double.parseDouble(d.getHdl());
//                    break;
//                case LDL:
//                    value = (int) Double.parseDouble(d.getLdl());
//                    break;
//            }

            if(max < value)
                max = value;

            if(min > value)
                min = value;

            if(value >= 18.5 || value < 25){
                colors.add(ActivityCompat.getColor(this, R.color.color_normal));
            }else if(value >= 25 || value < 30){
                colors.add(ActivityCompat.getColor(this, R.color.color_middle));
            }else if(value >= 30 || value <= 40){
                colors.add(ActivityCompat.getColor(this, R.color.color_low));
            }else{
                colors.add(ActivityCompat.getColor(this, R.color.color_danger));
            }

            if(date > 0 && value > 0){

                BarEntry entry = new BarEntry(calendar.get(Calendar.MONTH), value);
                entries.add(entry);
            }
        }

        BarDataSet barDataSet = new BarDataSet(entries, "BMI");

        barDataSet.setColors(colors);
        //Setting the size of the form in the legend
        barDataSet.setFormSize(5f);
        //showing the value of the bar, default true if not set
        barDataSet.setDrawValues(true);
        //setting the text size of the value of the bar
        barDataSet.setValueTextSize(12f);

        BarData data = new BarData(barDataSet);
        chart.setData(data);

        YAxis yAxis = chart.getAxisLeft();
        yAxis.setAxisMinimum(0);
        yAxis.setAxisMaximum(max+10f);

        XAxis xAxis = chart.getXAxis();
        xAxis.setValueFormatter(new StickyDateAxisValueFormatter());

        chart.invalidate();
    }

    public class StickyDateAxisValueFormatter extends IndexAxisValueFormatter {

        @Override
        public String getFormattedValue(float value) {

            // Convert float value to date string
            // Convert from days back to milliseconds to format time  to show to the user
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.MONTH, (int) value);
            long emissionsMilliSince1970Time = (long) value*1000;
            // Show time in local version
            Date timeMilliseconds = calendar.getTime();
            SimpleDateFormat dateTimeFormat = new SimpleDateFormat("MMM");

            return dateTimeFormat.format(timeMilliseconds);
        }
    }
}