import 'dart:math';
import 'dart:ui' as ui;
import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:sport/bean/sport_detail.dart';
import 'package:sport/services/Converter.dart';

const WEEK = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];

class ChartItem {
  final String createdAt;
  final int value;

  ChartItem(this.createdAt, this.value);
}

class Chart extends CustomPainter {
  final Paint _paint = Paint()
    ..color = const Color(0xffDCDCDC)
    ..strokeWidth = 0.5
    ..isAntiAlias = true;
  final Paint _paintCurrent = Paint()
    ..color = const Color(0xffFFC400)
    ..strokeWidth = 0.5
    ..isAntiAlias = true;

  static const Color _maxColor = Color(0xffFF5B1D);
  final Paint _maxPaint = Paint()
    ..color = _maxColor
    ..strokeWidth = 0.5
    ..isAntiAlias = true;

  final ParagraphStyle _labelStyle = ParagraphStyle(
    textAlign: TextAlign.left,
    fontSize: 8,
  );
  final ParagraphStyle _valueStyle = ParagraphStyle(
    textAlign: TextAlign.right,
    fontSize: 8,
  );
  final Paint columnPaint = Paint()..color =  const Color(0xffFFC400)
    ..isAntiAlias = true;

  double _zero = 0;
  double _paddingLeft = 35;
  double _paddingRight = 10;
  double _labelHeight = 30;

  int _valueSize = 7;
  int _valueSplit = 200;

  int type;
  List<ChartItem> records;
  DateTime dateTime;
  Map<String, num> values;
  bool drawMax = false;
  String unit = "kal";
  double _max = 750;
  int _currentIndex = 0;

  Chart({this.type, this.records, this.dateTime, this.drawMax, this.unit});

  void initData({double maxValue = 750, int valueSize = 7, int valueSplit = 200}) {
    _valueSize = valueSize;
    _valueSplit = valueSplit;
    values = {};
    var records = this.records ?? [];

    var now = DateTime.now();

    if (this.type == 0) {
      records.forEach((element) {
        var t = DateTime.parse(element.createdAt);
        values.update("${max(6, t.hour) - 5}", (value) => value + element.value, ifAbsent: () => Converter.toDouble(element.value));
      });
      for (int i = 6; i <= 24; i++) {
        values.putIfAbsent("$i", () => 0.0);
      }
      _currentIndex = -1;
    } else if (this.type == 1) {
      records.forEach((element) {
        var t = DateTime.parse(element.createdAt);
        values.update("${t.weekday == 0 ? 7 : t.weekday}", (value) => value + element.value, ifAbsent: () => Converter.toDouble(element.value));
      });
      for (int i = 1; i <= 7; i++) {
        values.putIfAbsent("$i", () => 0.0);
      }
      _currentIndex = (now.weekday == 0 ? 7 : now.weekday) - 1;
    } else if (this.type == 2) {
      records.forEach((element) {
        var t = DateTime.parse(element.createdAt);
        values.update("${t.day}", (value) => value + element.value, ifAbsent: () => Converter.toDouble(element.value));
      });
      for (int i = 1; i <= 31; i++) {
        values.putIfAbsent("$i", () => 0.0);
      }
      _currentIndex = now.day - 1;
    } else if (this.type == 3) {
      records.forEach((element) {
        values.update("${element.createdAt}", (value) => value + element.value, ifAbsent: () => Converter.toDouble(element.value));
      });
      for (int i = 1; i <= 12; i++) {
        values.putIfAbsent("$i", () => 0.0);
      }
      _currentIndex = now.month - 1;
    }
    values.values.forEach((element) {
      _max = max(maxValue, Converter.toDouble(element));
    });
    double diff = _max % _valueSplit;
    _max = max(maxValue, _max + diff);
    print("$values --- $_max $maxValue $diff");
  }

  @override
  void paint(Canvas canvas, Size size) {
    double zero = _zero = size.height - _labelHeight;

    // draw 值 行数
    int valuePadding = 10;
    canvas.drawLine(Offset(_paddingLeft, zero), Offset(size.width, zero), _paint);
    ParagraphBuilder pb = ParagraphBuilder(_valueStyle)
      ..pushStyle(ui.TextStyle(color: Color(0xff999999)))
      ..addText("0");
    ParagraphConstraints constraints = ParagraphConstraints(width: _paddingLeft - valuePadding);
    Paragraph paragraph = pb.build()..layout(constraints);
    paragraph.computeLineMetrics().forEach((element) {
      canvas.drawParagraph(paragraph, Offset(0, zero - element.baseline / 2));
    });

    canvas.drawLine(Offset(_paddingLeft, zero), Offset(_paddingLeft, 0), _paint);

    canvas.drawLine(Offset(size.width, zero), Offset(size.width, 0), _paint);

    double valueSpace = (size.height - _labelHeight) / _valueSize;
    for (var i = 0; i < _valueSize; i++) {
      canvas.drawLine(Offset(_paddingLeft, valueSpace * i), Offset(size.width, valueSpace * i), _paint);
      var value = (_valueSize - i) * _max ~/ _valueSize;
      ParagraphBuilder pb = ParagraphBuilder(_valueStyle)
        ..pushStyle(ui.TextStyle(color: Color(0xff999999)))
        ..addText(value < 1000 ? "${value}" : "${(value / 1000).toStringAsFixed(1)}k");
      ParagraphConstraints constraints = ParagraphConstraints(width: _paddingLeft - valuePadding);
      Paragraph paragraph = pb.build()..layout(constraints);
      paragraph.computeLineMetrics().forEach((element) {
        canvas.drawParagraph(paragraph, Offset(0, valueSpace * i - element.baseline / 2));
      });
      // print("${value / 1000} ${_max} ${(_valueSize - i) * _max ~/ _valueSize}");
    }

    // draw 数据列
    double left = _paddingLeft + 10;
    double width = size.width - _paddingRight - left; // 柱子的有效空间
    double valueStroke = 8; // 柱子宽度
    List<String> valueLabel = []; // 柱子数量
    int scaleCount = 0; // 刻度数量
    int scaleWeight = 3;
    if (this.type == 0) {
      // 日，按时间
      scaleWeight = 2;
      valueLabel = List.generate(10, (index) => "${6 + index * scaleWeight}:00");
      // valueStroke = width / valueLabel.length / scaleWeight - 5;
      scaleCount = 18;
    } else if (this.type == 1) {
      left += 20;
      width -= 40;
      scaleWeight = 1;
      valueLabel = List.generate(7, (index) => WEEK[index]);
      // valueStroke = 12;
      scaleCount = 6;
    } else if (this.type == 2) {
      DateTime now = this.dateTime;
//      DateTime now = DateTime(2019,2);
      DateTime startTime = DateTime.parse('${now.year}-${now.month < 10 ? '0${now.month}' : now.month}-01');
      DateTime endTime = DateTime.parse('${now.year}-${now.month + 1 < 10 ? '0${now.month + 1}' : now.month + 1}-01');
      int diffDay = endTime.difference(startTime).inDays;
      // List<int> days = [1, 8, 15, 22, diffDay == 28 ? 28:29];
      scaleCount = diffDay - 1;
      scaleWeight = 1;
      // valueLabel = days.map((e) => '$e/${now.month}').toList();
      // valueLabel = List.generate(diffDay ~/ scaleWeight + (scaleCount % scaleWeight == 0 ? 1 : 0), (index) => "${index * 2 + 1}");
      valueLabel = List.generate(diffDay, (index) => '${index + 1}');
      valueStroke = 5;
    } else if (this.type == 3) {
      valueLabel = List.generate(12, (index) => '${index + 1}');
      // valueStroke = 12;
      scaleCount = 12 - 1;
      scaleWeight = 1;
    }

    int labelSize = valueLabel.length;
    double labelSpace = (width) / labelSize;
    double scaleWidth = (width) / scaleCount;

    // if (this.type < 2) {
    //draw 刻度
    for (var i = 0; i <= scaleCount; i++) {
      canvas.drawLine(Offset(left + scaleWidth * i, zero), Offset(left + scaleWidth * i, zero - 3), _paint);
    }
    // }

    for (var i = 0; i < labelSize; i++) {
      int index = i;
      String label = valueLabel[i];
      if(type == 2 && i % 2 == 1) {
        if(i != _currentIndex)
        continue;
      }
      // print("1111111111111111111 $i $_currentIndex $label");
      bool curr = i == _currentIndex;
      ParagraphBuilder pb = ParagraphBuilder(_labelStyle)
        ..pushStyle(ui.TextStyle(color: curr ? const Color(0xffFFC400) : const Color(0xff999999)))
        ..addText(label);
      ParagraphConstraints constraints = ParagraphConstraints(width: labelSpace);
      Paragraph paragraph = pb.build()..layout(constraints);
      paragraph.computeLineMetrics().forEach((element) {
        var x = left + scaleWidth * scaleWeight * index - element.width / 2;
        var y = zero + 5;
        canvas.drawParagraph(paragraph, Offset(x, y));
        if(curr){
          x = x + element.width / 2 ;
          canvas.drawPath(Path()..moveTo(x, y + 11)..lineTo(x - 3, y + 14)..lineTo(x + 3, y + 14)..close(), _paintCurrent);
        }
      });

      if(type == 2){

      }
//
//      double l = left + scaleWidth * scaleWeight * i - valueStroke / 2;
//      Rect rect = Rect.fromLTRB(l, zero, l + valueStroke, 0);
//      print("value draw $rect");
//      Paint valuePaint = Paint()
//        ..shader = LinearGradient(
//          begin: Alignment.bottomCenter,
//          end: Alignment.topCenter,
//          colors: <Color>[Color(0xffFF9100), Color(0xffFFE600)],
//        ).createShader(rect);
//      canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(100)), valuePaint);
    }

    double maxVal = values.values.reduce((value, element) => max(value, element).toDouble());

    // if (this.type < 2) {
    for (var i = 0; i <= scaleCount; i++) {
      String key = '${i + 1}';
      // print("$key ${values[key]} 11111111111111   $scaleCount");
      if (!values.containsKey(key)) continue;
      num value = values[key];
      double l = left + scaleWidth * i - valueStroke / 2;
      Rect rect = Rect.fromLTRB(l, zero, l + valueStroke, calValue(value));
      canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(100)), columnPaint);

      if (this.drawMax) {
        if (maxVal <= value) {
          if (maxVal > 0) {
            double offsetY = calValue(maxVal);
            double offsetX = _paddingLeft;
            while (offsetX < size.width) {
              canvas.drawLine(Offset(offsetX, offsetY), Offset(min(offsetX + 3, size.width), offsetY), _maxPaint);
              offsetX += 5;
            }
            ParagraphBuilder unit = ParagraphBuilder(_labelStyle)
              ..pushStyle(ui.TextStyle(color: _maxColor))
              ..addText("${value.round()}${this.unit}");
            ParagraphConstraints pc = ParagraphConstraints(width: size.width);
            paragraph = unit.build()..layout(pc);
            paragraph.computeLineMetrics().forEach((element) {
              var x = l + valueStroke / 2 - element.width / 2;
              canvas.drawParagraph(paragraph, Offset(x, offsetY -element.baseline - 10));
              x = l + valueStroke / 2 ;
              canvas.drawPath(Path()..moveTo(x, offsetY - 4)..lineTo(x - 3, offsetY - 7)..lineTo(x + 3, offsetY - 7)..close(), _maxPaint);
            });
          }
        }
      }
    }
    // } else {
    //   Path path = Path();
    //   path.moveTo(_paddingLeft, calValue(values['1']));
    //   Path area = Path()
    //     ..moveTo(_paddingLeft, zero)
    //     ..lineTo(_paddingLeft, calValue(values['1']));
    //   for (var i = 1; i <= scaleCount; i++) {
    //     path.lineTo(left + scaleWidth * i, calValue(values['$i']));
    //     area.lineTo(left + scaleWidth * i, calValue(values['$i']));
    //   }
    //   area.lineTo(size.width, zero);
    //   area.close();
    //
    //   canvas.save();
    //   canvas.clipPath(area);
    //   Rect rect = Rect.fromLTRB(_paddingLeft, zero, size.width, calValue(_max));
    //   Paint valuePaint = Paint()
    //     ..shader = LinearGradient(
    //       begin: Alignment.bottomCenter,
    //       end: Alignment.topCenter,
    //       colors: <Color>[Color(0xffFFC400), Color(0x50FFFFFF)],
    //     ).createShader(rect);
    //   canvas.drawRect(rect, valuePaint);
    //   canvas.restore();
    //
    //   canvas.drawPath(path, _linePaint);
    // }
  }

  double calValue(num value) {
    if (value == null) return _zero;
    return max(0, _zero - _zero * value / _max);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}
