import 'dart:math' as math;

import 'package:charts_flutter/flutter.dart' as charts;
import 'package:diplomaticquarterapp/core/enum/viewstate.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/insert_user_activity_request_model.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/user_detail_model.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/user_progress_for_month_data_model.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/user_progress_for_today_data_model.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/user_progress_for_week_data_model.dart';
import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/H2O_service.dart';
import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart';
import 'package:diplomaticquarterapp/widgets/charts/custom_line_chart.dart';

import '../../../locator.dart';

class H2OViewModel extends BaseViewModel {
  H2OService _h2OService = locator<H2OService>();

  //
  // List<charts.Series> userProgressForWeekDataSeries;
  List<LineChartModel> userProgressForWeekDataSeries;
  List<LineChartModel> userProgressForMonthDataSeries;

  // List<charts.Series> userProgressForMonthDataSeries;

  UserDetailModel get userDetail => _h2OService.userDetailModel;

  UserProgressForTodayDataModel get userProgressData {
    if (_h2OService.userProgressForTodayDataList.length != 0) return _h2OService.userProgressForTodayDataList[0];
    return null;
  }

  Future getUserDetail() async {
    // if(_h2OService.userProgressForTodayDataList.length==0){
    setState(ViewState.Busy);
    await _h2OService.getUserDetail();
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.Error);
    } else {
      setState(ViewState.Idle);
    }
  }

  Future updateUserDetail(UserDetailModel userDetailModel, Function(bool) onResponse) async {
    setState(ViewState.Busy);

    await _h2OService.updateUserDetail(userDetailModel);
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.Error);
      onResponse(false);
    } else {
      _h2OService.userDetailModel = userDetailModel;
      setState(ViewState.Idle);
      onResponse(true);
    }
  }

  Future getUserProgressForTodayData() async {
    // if(_h2OService.userProgressForTodayDataList.length==0){
    setState(ViewState.Busy);
    await _h2OService.getUserProgressForTodayData();
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.Error);
    } else {
      setState(ViewState.Idle);
    }
  }

  Future getUserProgressForWeekData() async {
    setState(ViewState.Busy);
    await _h2OService.getUserProgressForWeekData();
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.Error);
    } else {
      // userProgressForWeekDataSeries = createUserProgressForWeekDataSeries();
      userProgressForWeekDataSeries = createUserProgressForWeekDataSeriesNew();
      setState(ViewState.Idle);
    }
  }

  Future getUserProgressForMonthData() async {
    setState(ViewState.Busy);
    await _h2OService.getUserProgressForMonthData();
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.Error);
    } else {
      userProgressForMonthDataSeries = createUserProgressForMonthDataSeriesNew();
      setState(ViewState.Idle);
    }
  }

  List<charts.Series<ChartSeries, String>> createUserProgressForWeekDataSeries() {
    List<ChartSeries> globalData = [];
    _h2OService.userProgressForWeekDataList.forEach((UserProgressForWeekDataModel data) {
      globalData.add(new ChartSeries(data.dayName, data.percentageConsumed));
    });
    Iterable<int> minMaxList = globalData.map((e) => e.x).toList();
    int maxValue = minMaxList.isEmpty ? 0 : minMaxList.reduce(math.max);
    int minValue = minMaxList.isEmpty ? 0 : minMaxList.reduce(math.min);

    if (maxValue == 0 && minValue == 0) {
      maxValue = 1;
      minValue = -1;
    }
    return [
      new charts.Series<ChartSeries, String>(
        id: 'Global Revenue',
        domainFn: (ChartSeries sales, _) => sales.y,
        measureFn: (ChartSeries sales, _) => sales.x,
        measureLowerBoundFn: (ChartSeries sales, _) => minValue,
        measureUpperBoundFn: (ChartSeries sales, _) => maxValue,
        data: globalData,
      ),
    ];
  }

  List<LineChartModel> createUserProgressForWeekDataSeriesNew() {
    List<LineChartModel> list = [];

    _h2OService.userProgressForWeekDataList.forEach((UserProgressForWeekDataModel data) {
      list.add(new LineChartModel(data.dayName, data.percentageConsumed));
    });
    return list;
  }

  List<LineChartModel> createUserProgressForMonthDataSeriesNew() {
    List<LineChartModel> list = [];
    _h2OService.userProgressForMonthDataList.forEach((UserProgressForMonthDataModel data) {
      list.add(new LineChartModel(data.monthName, data.percentageConsumed));
    });
    return list;
  }

  List<charts.Series<ChartSeries, String>> createUserProgressForMonthDataSeries() {
    List<ChartSeries> globalData = [];
    _h2OService.userProgressForMonthDataList.forEach((UserProgressForMonthDataModel data) {
      globalData.add(new ChartSeries(data.monthName, data.percentageConsumed));
    });
    return [
      new charts.Series<ChartSeries, String>(
        id: 'Global Revenue',
        domainFn: (ChartSeries sales, _) => sales.y,
        measureFn: (ChartSeries sales, _) => sales.x,
        data: globalData,
      ),
    ];
  }

  Future insertUserActivity(InsertUserActivityRequestModel insertUserActivityRequestModel) async {
    setState(ViewState.BusyLocal);
    insertUserActivityRequestModel.mobileNumber = user.mobileNumber.substring(1);
    insertUserActivityRequestModel.identificationNo = user.patientIdentificationNo;

    await _h2OService.insertUserActivity(insertUserActivityRequestModel);
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.ErrorLocal);
    } else {
      setState(ViewState.Idle);
    }
  }

  Future undoUserActivity() async {
    setState(ViewState.BusyLocal);
    await _h2OService.undoUserActivity();
    if (_h2OService.hasError) {
      error = _h2OService.error;
      setState(ViewState.ErrorLocal);
    } else {
      setState(ViewState.Idle);
    }
  }
}

/// Sample ordinal data type.
class ChartSeries {
  final String y;
  final int x;

  ChartSeries(this.y, this.x);
}
