import 'dart:async';

import 'package:flutter/material.dart';
import 'package:liftmanager/internal/maintenance/model/maintenance_count_item.dart';
import 'package:liftmanager/res/resources.dart';
import 'package:liftmanager/utils/utils.dart';
import 'package:liftmanager/widgets/calendar/calendar_title.dart';
import 'package:tuple/tuple.dart';


typedef DayBuilder(BuildContext context, DateTime day);

class Calendar extends StatefulWidget {
  final ValueChanged<DateTime> onDateSelected;
  final ValueChanged<Tuple2<DateTime, DateTime>> onSelectedRangeChange;
  final bool isExpandable;
  final DayBuilder dayBuilder;
  final bool showChevronsToChangeRange;
  final bool showTodayAction;
  final bool showCalendarPickerIcon;
  final DateTime initialCalendarDateOverride;

  Calendar(
      {this.onDateSelected,
        this.onSelectedRangeChange,
        this.isExpandable: false,
        this.dayBuilder,
        this.showTodayAction: true,
        this.showChevronsToChangeRange: true,
        this.showCalendarPickerIcon: true,
        this.initialCalendarDateOverride});

  final mCalendarState = CalendarState();

  today() {
    mCalendarState.resetToToday();
  }

  DateTime currentSelected(){
    return mCalendarState._selectedDate;
  }


//  updateState(int i){
//    mCalendarState.mtState = i;
//  }

  void updateState(List<MantenanceCountItem> arrCount) {
    mCalendarState.updateState(arrCount);
  }

  @override
  CalendarState createState() {
    return mCalendarState;
  }
}

class CalendarState extends State<Calendar> {
  final calendarUtils = new Utils();
  List<DateTime> selectedMonthsDays;
  Iterable<DateTime> selectedWeeksDays;
  DateTime _selectedDate = new DateTime.now();
  DateTime _selectedPageDate = new DateTime.now();
  String currentMonth;
  bool isExpanded = false;
  String displayMonth;
  List<MantenanceCountItem> arrCount = [];

  DateTime get selectedDate => _selectedDate;

  void initState() {
    super.initState();
    if (widget.initialCalendarDateOverride != null) {
      _selectedDate = widget.initialCalendarDateOverride;
    }
    _selectedPageDate = _selectedDate;

    selectedMonthsDays = Utils.daysInMonth(_selectedDate);
    var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
    var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);
    selectedWeeksDays =
        Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
            .toList()
            .sublist(0, 7);
    displayMonth = Utils.formatMonth(_selectedDate);
  }

  Widget get nameAndIconRow {
    var leftInnerIcon;
    var rightInnerIcon;
    var leftOuterIcon;
    var rightOuterIcon;

    if (widget.showCalendarPickerIcon) {
      rightInnerIcon = new IconButton(
        onPressed: () => selectDateFromPicker(),
        icon: new Icon(Icons.calendar_today),
      );
    } else {
      rightInnerIcon = new Container();
    }

    if (widget.showChevronsToChangeRange) {
      leftOuterIcon = new IconButton(
        onPressed: isExpanded ? previousMonth : previousWeek,
        icon: new Icon(Icons.chevron_left),
      );
      rightOuterIcon = new IconButton(
        onPressed: isExpanded ? nextMonth : nextWeek,
        icon: new Icon(Icons.chevron_right),
      );
    } else {
      leftOuterIcon = new Container();
      rightOuterIcon = new Container();
    }

    if (widget.showTodayAction) {
      leftInnerIcon = new InkWell(
        child: Container(
          child: Image.asset("images/icon_today.png"),
        ),
        onTap: resetToToday,
      );
    } else {
      leftInnerIcon = new Container();
    }

    return Container(
        padding: EdgeInsets.only(left: 15, right: 15),
        decoration: BoxDecoration(
          color: Colours.app_main,
          gradient: const LinearGradient(
              colors: [Color(0xFF00D9FF), Color(0xFF0287FF)]),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            rightInnerIcon ?? new Container(),
            rightOuterIcon ?? new Container(),
            new GestureDetector(
              onTap: () => selectDateFromPicker(),
              child: Text(
                displayMonth,
                style: new TextStyle(fontSize: 15.0, color: Colors.white),
              ),
            ),
            leftOuterIcon ?? new Container(),
            leftInnerIcon ?? new Container(),
          ],
        ));
  }

  Widget get calendarGridView {
    return new Container(
      child: new GestureDetector(
        onHorizontalDragStart: (gestureDetails) => beginSwipe(gestureDetails),
        onHorizontalDragUpdate: (gestureDetails) =>
            getDirection(gestureDetails),
        onHorizontalDragEnd: (gestureDetails) => endSwipe(gestureDetails),
        onVerticalDragStart: (gestureDetails) =>
            beginVerticalSwipe(gestureDetails),
        onVerticalDragUpdate: (gestureDetails) =>
            updateVerticalSwipe(gestureDetails),
        onVerticalDragEnd: (gestureDetails) => endVerticalSwipe(gestureDetails),
        child: new GridView.count(
          physics: NeverScrollableScrollPhysics(),
          //禁止GridView滚动事件，避免冲突
          shrinkWrap: true,
          crossAxisCount: 7,
          padding: new EdgeInsets.only(bottom: 0.0),
          children: calendarBuilder(),
        ),
      ),
    );
  }

  List<Widget> calendarWeek() {
    List<Widget> dayWidgets = [];
    Utils.weekdays.forEach(
          (day) {
        dayWidgets.add(
          new CalendarTile(
//            weekBgColor: Colors.white,
            dayOfWeekStyles: TextStyle(color: Colors.white),
            isDayOfWeek: true,
            dayOfWeek: day,
          ),
        );
      },
    );
    return dayWidgets;
  }

  List<Widget> calendarBuilder() {
    List<Widget> dayWidgets = [];
    List<DateTime> calendarDays =
    isExpanded ? selectedMonthsDays : selectedWeeksDays;

//    Utils.weekdays.forEach(
//          (day) {
//        dayWidgets.add(
//          new CalendarTile(
////            weekBgColor: MyColors.app_main,
//            dayOfWeekStyles:TextStyle(color: Colors.white),
//            isDayOfWeek: true,
//            dayOfWeek: day,
//          ),
//        );
//      },
//    );

    bool monthStarted = false;
    bool monthEnded = false;

    calendarDays.forEach(
          (day) {
        if (monthStarted && day.day == 01) {
          monthEnded = true;
        }

        if (Utils.isFirstDayOfMonth(day)) {
          monthStarted = true;
        }

        if (this.widget.dayBuilder != null) {
          dayWidgets.add(
            new CalendarTile(
              child: this.widget.dayBuilder(context, day),
              date: day,
              onDateSelected: () => handleSelectedDateAndUserCallback(day),
            ),
          );
        } else {
          dayWidgets.add(
            new CalendarTile(
              onDateSelected: () => handleSelectedDateAndUserCallback(day),
              date: day,
              dateStyles: configureDateStyle(monthStarted, monthEnded),
              isSelected: "${_selectedDate.year},${_selectedDate.month}" ==
                  "${_selectedPageDate.year},${_selectedPageDate.month}"
                  ? Utils.isSameDay(selectedDate, day)
                  : false,
              mtState: isMtState(day),
            ),
          );
        }
      },
    );
    return dayWidgets;
  }

  TextStyle configureDateStyle(monthStarted, monthEnded) {
    TextStyle dateStyles;
    if (isExpanded) {
      dateStyles = monthStarted && !monthEnded
          ? new TextStyle(color:Colours.dark_bg_gray, fontSize: 13)
          : new TextStyle(color: Colours.bg_gray, fontSize: 13);
    } else {
      dateStyles = new TextStyle(color: Colours.dark_bg_gray, fontSize: 13);
    }
    return dateStyles;
  }

  Widget get expansionButtonRow {
    if (widget.isExpandable) {
      return new Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          new Text(Utils.fullDayFormat(selectedDate)),
          new IconButton(
            iconSize: 20.0,
            padding: new EdgeInsets.all(0.0),
            onPressed: toggleExpanded,
            icon: isExpanded
                ? new Icon(Icons.arrow_drop_up)
                : new Icon(Icons.arrow_drop_down),
          ),
        ],
      );
    } else {
      return new Container();
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          nameAndIconRow,
          Container(
            decoration: BoxDecoration(color: Colours.app_main,
              gradient: const LinearGradient(
                  colors: [Color(0xFF00D9FF), Color(0xFF0287FF)]),
            ),
            child: GridView.count(
              shrinkWrap: true,
              crossAxisCount: 7,
              padding: new EdgeInsets.only(bottom: 0.0),
              children: calendarWeek(),
            ),
          ),
          new ExpansionCrossFade(
            collapsed: calendarGridView,
            expanded: calendarGridView,
            isExpanded: isExpanded,
          ),
//          expansionButtonRow
        ],
      ),
    );
  }

  resetToToday() {
    print("resetToToday");
    _selectedDate = new DateTime.now();
    _selectedPageDate = _selectedDate;
//    if(isExpanded){
    var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedDate);
    var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedDate);
    var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
    var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);
    setState(() {
      selectedWeeksDays =
          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
              .toList();
      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
      selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);
      displayMonth = Utils.formatMonth(_selectedDate);
    });
//    }else{
//      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
//      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);
//      setState(() {
//        selectedWeeksDays =
//            Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
//                .toList();
//        displayMonth = Utils.formatMonth(_selectedDate);
//      });
//    }

    _launchDateSelectionCallback(_selectedDate);
  }

  void nextMonth() {
    setState(() {
//      _selectedDate = Utils.nextMonth(_selectedDate);
//      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedDate);
//      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedDate);
//      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
//      selectedMonthsDays = Utils.daysInMonth(_selectedDate);
//      displayMonth = Utils.formatMonth(_selectedDate);

      _selectedPageDate = Utils.nextMonth(_selectedPageDate);
      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedPageDate);
      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedPageDate);
      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
      selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);
      displayMonth = Utils.formatMonth(_selectedPageDate);
    });
  }

  void previousMonth() {
    setState(() {
//      _selectedDate = Utils.previousMonth(_selectedDate);
//      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedDate);
//      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedDate);
//      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
//      selectedMonthsDays = Utils.daysInMonth(_selectedDate);
//      displayMonth = Utils.formatMonth(_selectedDate);
      _selectedPageDate = Utils.previousMonth(_selectedPageDate);
      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedPageDate);
      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedPageDate);
      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
      selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);
      displayMonth = Utils.formatMonth(_selectedPageDate);
    });
  }

  void nextWeek() {
    setState(() {
//      _selectedDate = Utils.nextWeek(_selectedDate);
//      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
//      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);
//      updateSelectedRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek);
//      selectedWeeksDays =
//          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
//              .toList()
//              .sublist(0, 7);
//      displayMonth = Utils.formatMonth(_selectedDate);
      _selectedPageDate = Utils.nextWeek(_selectedPageDate);
      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedPageDate);
      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedPageDate);
//      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedDate);
//      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedDate);
//      updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
      updateSelectedRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek);
      selectedWeeksDays =
          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
              .toList()
              .sublist(0, 7);
      selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);

      displayMonth = Utils.formatMonth(_selectedPageDate);
    });
//    _launchDateSelectionCallback(_selectedDate);
    _launchDateSelectionCallback(_selectedPageDate);
  }

  void previousWeek() {
    setState(() {
//      _selectedDate = Utils.previousWeek(_selectedDate);
//      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
//      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);
//      updateSelectedRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek);
//      selectedWeeksDays =
//          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
//              .toList()
//              .sublist(0, 7);
//      displayMonth = Utils.formatMonth(_selectedDate);
      _selectedPageDate = Utils.previousWeek(_selectedPageDate);
      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedPageDate);
      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedPageDate);
      updateSelectedRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek);
      selectedWeeksDays =
          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
              .toList()
              .sublist(0, 7);
      selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);
      displayMonth = Utils.formatMonth(_selectedPageDate);
    });
//    _launchDateSelectionCallback(_selectedDate);
    _launchDateSelectionCallback(_selectedPageDate);
  }

  void updateSelectedRange(DateTime start, DateTime end) {
    var selectedRange = new Tuple2<DateTime, DateTime>(start, end);
    if (widget.onSelectedRangeChange != null) {
      widget.onSelectedRangeChange(selectedRange);
    }
  }

  Future<Null> selectDateFromPicker() async {
    DateTime selected = await showDatePicker(
      context: context,
      initialDate: _selectedDate ?? new DateTime.now(),
      firstDate: new DateTime(1960),
      lastDate: new DateTime(2050),
    );

    if (selected != null) {
      _selectedDate = selected;
      _selectedPageDate = _selectedDate;
      var firstDateOfNewMonth = Utils.firstDayOfMonth(_selectedDate);
      var lastDateOfNewMonth = Utils.lastDayOfMonth(_selectedDate);
      var firstDayOfCurrentWeek = Utils.firstDayOfWeek(_selectedDate);
      var lastDayOfCurrentWeek = Utils.lastDayOfWeek(_selectedDate);

      ///todo
      setState(() {
        selectedWeeksDays =
            Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
                .toList();
        updateSelectedRange(firstDateOfNewMonth, lastDateOfNewMonth);
        selectedMonthsDays = Utils.daysInMonth(_selectedPageDate);
        displayMonth = Utils.formatMonth(_selectedDate);
      });
      // updating selected date range based on selected week
//      updateSelectedRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek);
      _launchDateSelectionCallback(_selectedDate);
    }
  }

  var gestureStart;
  var gestureDirection;

  void beginSwipe(DragStartDetails gestureDetails) {
    gestureStart = gestureDetails.globalPosition.dx;
  }

  void getDirection(DragUpdateDetails gestureDetails) {
    if (gestureDetails.globalPosition.dx < gestureStart) {
      gestureDirection = 'rightToLeft';
    } else {
      gestureDirection = 'leftToRight';
    }
  }

  void endSwipe(DragEndDetails gestureDetails) {
    if (gestureDirection == 'rightToLeft') {
      if (isExpanded) {
        nextMonth();
      } else {
        nextWeek();
      }
    } else {
      if (isExpanded) {
        previousMonth();
      } else {
        previousWeek();
      }
    }
  }

  var gestureVertivalStart;
  var gestureVertivalDirection;

  void beginVerticalSwipe(DragStartDetails gestureDetails) {
    gestureVertivalStart = gestureDetails.globalPosition.dy;
  }

  void updateVerticalSwipe(DragUpdateDetails gestureDetails) {
    if (gestureDetails.globalPosition.dy < gestureVertivalStart) {
      gestureVertivalDirection = 'rightToTop';
    } else {
      gestureVertivalDirection = 'leftToBotton';
    }
  }

  void endVerticalSwipe(DragEndDetails gestureDetails) {
    if (gestureVertivalDirection == 'rightToTop') {
      if (widget.isExpandable) {
        setState(() => isExpanded = false);
      }
    } else {
      if (widget.isExpandable) {
        setState(() => isExpanded = true);
      }
    }
  }

  void toggleExpanded() {
    if (widget.isExpandable) {
      setState(() => isExpanded = !isExpanded);
    }
  }

  void handleSelectedDateAndUserCallback(DateTime day) {
    var firstDayOfCurrentWeek = Utils.firstDayOfWeek(day);
    var lastDayOfCurrentWeek = Utils.lastDayOfWeek(day);
    setState(() {
      _selectedDate = day;
      selectedWeeksDays =
          Utils.daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek)
              .toList();
      selectedMonthsDays = Utils.daysInMonth(day);
    });
    _launchDateSelectionCallback(day);
  }

  void _launchDateSelectionCallback(DateTime day) {
    if (widget.onDateSelected != null) {
      widget.onDateSelected(day);
    }
  }

  updateState(List<MantenanceCountItem> arrCount){
    this.arrCount = arrCount;
    setState(() {

    });
  }

//  TextStyle configureDateStyle(monthStarted, monthEnded) {
//    TextStyle dateStyles;
//    if (isExpanded) {
//      dateStyles = monthStarted && !monthEnded
//          ? new TextStyle(color: MyColors.ff_1a, fontSize: dip_f(13))
//          : new TextStyle(color: MyColors.ff_99, fontSize: dip_f(13));
//    } else {
//      dateStyles = new TextStyle(color: MyColors.ff_1a, fontSize: dip_f(13));
//    }
//    return dateStyles;
//  }
  int isMtState(DateTime dateTime) {
    if (_selectedPageDate.month != dateTime.month||_selectedPageDate.year != dateTime.year) {
      return 0;
    }
    int mtState = 0;
    for (int i = 0; i < arrCount.length; i++) {
      if(DateTime.parse('${arrCount[i].planDate}').day ==dateTime.day){

        if(arrCount[i].complete>0){
          mtState = 3;
        }
        if(arrCount[i].waitingMaintenance>0){
          mtState = 1;
        }
        if(arrCount[i].inProgress>0){
          mtState = 2;
        }
        if(arrCount[i].overdue>0){
          mtState = 4;
        }
//        if(arrCount[i].statuteOverdueCount>0||arrCount[i].overdueCount>0){
//          mtState = 4;
//        }
      }
    }
    return mtState;
  }
}

class ExpansionCrossFade extends StatelessWidget {
  final Widget collapsed;
  final Widget expanded;
  final bool isExpanded;

  ExpansionCrossFade({this.collapsed, this.expanded, this.isExpanded});

  @override
  Widget build(BuildContext context) {
    return new Flexible(
      flex: 1,
      child: new AnimatedCrossFade(
        firstChild: collapsed,
        secondChild: expanded,
        firstCurve: const Interval(0.0, 1.0, curve: Curves.fastOutSlowIn),
        secondCurve: const Interval(0.0, 1.0, curve: Curves.fastOutSlowIn),
        sizeCurve: Curves.decelerate,
        crossFadeState:
        isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
        duration: const Duration(milliseconds: 100),
      ),
    );
  }
}
