'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var tslib_es6 = require('../../../../../../tslib@2.3.0/node_modules/tslib/tslib.es6.js');
var util = require('../../../../../../zrender@6.0.0/node_modules/zrender/lib/core/util.js');
require('../../util/graphic.js');
var labelStyle = require('../../label/labelStyle.js');
var format = require('../../util/format.js');
var number = require('../../util/number.js');
var Component = require('../../view/Component.js');
var locale = require('../../core/locale.js');
var Rect = require('../../../../../../zrender@6.0.0/node_modules/zrender/lib/graphic/shape/Rect.js');
var Polyline = require('../../../../../../zrender@6.0.0/node_modules/zrender/lib/graphic/shape/Polyline.js');
var Text = require('../../../../../../zrender@6.0.0/node_modules/zrender/lib/graphic/Text.js');

var CalendarView = /** @class */function (_super) {
  tslib_es6.__extends(CalendarView, _super);
  function CalendarView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;
    _this.type = CalendarView.type;
    return _this;
  }
  CalendarView.prototype.render = function (calendarModel, ecModel, api) {
    var group = this.group;
    group.removeAll();
    var coordSys = calendarModel.coordinateSystem;
    // range info
    var rangeData = coordSys.getRangeInfo();
    var orient = coordSys.getOrient();
    // locale
    var localeModel = ecModel.getLocaleModel();
    this._renderDayRect(calendarModel, rangeData, group);
    // _renderLines must be called prior to following function
    this._renderLines(calendarModel, rangeData, orient, group);
    this._renderYearText(calendarModel, rangeData, orient, group);
    this._renderMonthText(calendarModel, localeModel, orient, group);
    this._renderWeekText(calendarModel, localeModel, rangeData, orient, group);
  };
  // render day rect
  CalendarView.prototype._renderDayRect = function (calendarModel, rangeData, group) {
    var coordSys = calendarModel.coordinateSystem;
    var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle();
    var sw = coordSys.getCellWidth();
    var sh = coordSys.getCellHeight();
    for (var i = rangeData.start.time; i <= rangeData.end.time; i = coordSys.getNextNDay(i, 1).time) {
      var point = coordSys.dataToCalendarLayout([i], false).tl;
      // every rect
      var rect = new Rect.default({
        shape: {
          x: point[0],
          y: point[1],
          width: sw,
          height: sh
        },
        cursor: 'default',
        style: itemRectStyleModel
      });
      group.add(rect);
    }
  };
  // render separate line
  CalendarView.prototype._renderLines = function (calendarModel, rangeData, orient, group) {
    var self = this;
    var coordSys = calendarModel.coordinateSystem;
    var lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle();
    var show = calendarModel.get(['splitLine', 'show']);
    var lineWidth = lineStyleModel.lineWidth;
    this._tlpoints = [];
    this._blpoints = [];
    this._firstDayOfMonth = [];
    this._firstDayPoints = [];
    var firstDay = rangeData.start;
    for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
      addPoints(firstDay.formatedDate);
      if (i === 0) {
        firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
      }
      var date = firstDay.date;
      date.setMonth(date.getMonth() + 1);
      firstDay = coordSys.getDateInfo(date);
    }
    addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);
    function addPoints(date) {
      self._firstDayOfMonth.push(coordSys.getDateInfo(date));
      self._firstDayPoints.push(coordSys.dataToCalendarLayout([date], false).tl);
      var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);
      self._tlpoints.push(points[0]);
      self._blpoints.push(points[points.length - 1]);
      show && self._drawSplitline(points, lineStyleModel, group);
    }
    // render top/left line
    show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);
    // render bottom/right line
    show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);
  };
  // get points at both ends
  CalendarView.prototype._getEdgesPoints = function (points, lineWidth, orient) {
    var rs = [points[0].slice(), points[points.length - 1].slice()];
    var idx = orient === 'horizontal' ? 0 : 1;
    // both ends of the line are extend half lineWidth
    rs[0][idx] = rs[0][idx] - lineWidth / 2;
    rs[1][idx] = rs[1][idx] + lineWidth / 2;
    return rs;
  };
  // render split line
  CalendarView.prototype._drawSplitline = function (points, lineStyle, group) {
    var poyline = new Polyline.default({
      z2: 20,
      shape: {
        points: points
      },
      style: lineStyle
    });
    group.add(poyline);
  };
  // render month line of one week points
  CalendarView.prototype._getLinePointsOfOneWeek = function (calendarModel, date, orient) {
    var coordSys = calendarModel.coordinateSystem;
    var parsedDate = coordSys.getDateInfo(date);
    var points = [];
    for (var i = 0; i < 7; i++) {
      var tmpD = coordSys.getNextNDay(parsedDate.time, i);
      var point = coordSys.dataToCalendarLayout([tmpD.time], false);
      points[2 * tmpD.day] = point.tl;
      points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
    }
    return points;
  };
  CalendarView.prototype._formatterLabel = function (formatter, params) {
    if (util.isString(formatter) && formatter) {
      return format.formatTplSimple(formatter, params);
    }
    if (util.isFunction(formatter)) {
      return formatter(params);
    }
    return params.nameMap;
  };
  CalendarView.prototype._yearTextPositionControl = function (textEl, point, orient, position, margin) {
    var x = point[0];
    var y = point[1];
    var aligns = ['center', 'bottom'];
    if (position === 'bottom') {
      y += margin;
      aligns = ['center', 'top'];
    } else if (position === 'left') {
      x -= margin;
    } else if (position === 'right') {
      x += margin;
      aligns = ['center', 'top'];
    } else {
      // top
      y -= margin;
    }
    var rotate = 0;
    if (position === 'left' || position === 'right') {
      rotate = Math.PI / 2;
    }
    return {
      rotation: rotate,
      x: x,
      y: y,
      style: {
        align: aligns[0],
        verticalAlign: aligns[1]
      }
    };
  };
  // render year
  CalendarView.prototype._renderYearText = function (calendarModel, rangeData, orient, group) {
    var yearLabel = calendarModel.getModel('yearLabel');
    if (!yearLabel.get('show')) {
      return;
    }
    var margin = yearLabel.get('margin');
    var pos = yearLabel.get('position');
    if (!pos) {
      pos = orient !== 'horizontal' ? 'top' : 'left';
    }
    var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
    var xc = (points[0][0] + points[1][0]) / 2;
    var yc = (points[0][1] + points[1][1]) / 2;
    var idx = orient === 'horizontal' ? 0 : 1;
    var posPoints = {
      top: [xc, points[idx][1]],
      bottom: [xc, points[1 - idx][1]],
      left: [points[1 - idx][0], yc],
      right: [points[idx][0], yc]
    };
    var name = rangeData.start.y;
    if (+rangeData.end.y > +rangeData.start.y) {
      name = name + '-' + rangeData.end.y;
    }
    var formatter = yearLabel.get('formatter');
    var params = {
      start: rangeData.start.y,
      end: rangeData.end.y,
      nameMap: name
    };
    var content = this._formatterLabel(formatter, params);
    var yearText = new Text.default({
      z2: 30,
      style: labelStyle.createTextStyle(yearLabel, {
        text: content
      }),
      silent: yearLabel.get('silent')
    });
    yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));
    group.add(yearText);
  };
  CalendarView.prototype._monthTextPositionControl = function (point, isCenter, orient, position, margin) {
    var align = 'left';
    var vAlign = 'top';
    var x = point[0];
    var y = point[1];
    if (orient === 'horizontal') {
      y = y + margin;
      if (isCenter) {
        align = 'center';
      }
      if (position === 'start') {
        vAlign = 'bottom';
      }
    } else {
      x = x + margin;
      if (isCenter) {
        vAlign = 'middle';
      }
      if (position === 'start') {
        align = 'right';
      }
    }
    return {
      x: x,
      y: y,
      align: align,
      verticalAlign: vAlign
    };
  };
  // render month and year text
  CalendarView.prototype._renderMonthText = function (calendarModel, localeModel, orient, group) {
    var monthLabel = calendarModel.getModel('monthLabel');
    if (!monthLabel.get('show')) {
      return;
    }
    var nameMap = monthLabel.get('nameMap');
    var margin = monthLabel.get('margin');
    var pos = monthLabel.get('position');
    var align = monthLabel.get('align');
    var termPoints = [this._tlpoints, this._blpoints];
    if (!nameMap || util.isString(nameMap)) {
      if (nameMap) {
        // case-sensitive
        localeModel = locale.getLocaleModel(nameMap) || localeModel;
      }
      // PENDING
      // for ZH locale, original form is `一月` but current form is `1月`
      nameMap = localeModel.get(['time', 'monthAbbr']) || [];
    }
    var idx = pos === 'start' ? 0 : 1;
    var axis = orient === 'horizontal' ? 0 : 1;
    margin = pos === 'start' ? -margin : margin;
    var isCenter = align === 'center';
    var labelSilent = monthLabel.get('silent');
    for (var i = 0; i < termPoints[idx].length - 1; i++) {
      var tmp = termPoints[idx][i].slice();
      var firstDay = this._firstDayOfMonth[i];
      if (isCenter) {
        var firstDayPoints = this._firstDayPoints[i];
        tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
      }
      var formatter = monthLabel.get('formatter');
      var name_1 = nameMap[+firstDay.m - 1];
      var params = {
        yyyy: firstDay.y,
        yy: (firstDay.y + '').slice(2),
        MM: firstDay.m,
        M: +firstDay.m,
        nameMap: name_1
      };
      var content = this._formatterLabel(formatter, params);
      var monthText = new Text.default({
        z2: 30,
        style: util.extend(labelStyle.createTextStyle(monthLabel, {
          text: content
        }), this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)),
        silent: labelSilent
      });
      group.add(monthText);
    }
  };
  CalendarView.prototype._weekTextPositionControl = function (point, orient, position, margin, cellSize) {
    var align = 'center';
    var vAlign = 'middle';
    var x = point[0];
    var y = point[1];
    var isStart = position === 'start';
    if (orient === 'horizontal') {
      x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
      align = isStart ? 'right' : 'left';
    } else {
      y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
      vAlign = isStart ? 'bottom' : 'top';
    }
    return {
      x: x,
      y: y,
      align: align,
      verticalAlign: vAlign
    };
  };
  // render weeks
  CalendarView.prototype._renderWeekText = function (calendarModel, localeModel, rangeData, orient, group) {
    var dayLabel = calendarModel.getModel('dayLabel');
    if (!dayLabel.get('show')) {
      return;
    }
    var coordSys = calendarModel.coordinateSystem;
    var pos = dayLabel.get('position');
    var nameMap = dayLabel.get('nameMap');
    var margin = dayLabel.get('margin');
    var firstDayOfWeek = coordSys.getFirstDayOfWeek();
    if (!nameMap || util.isString(nameMap)) {
      if (nameMap) {
        // case-sensitive
        localeModel = locale.getLocaleModel(nameMap) || localeModel;
      }
      // Use the first letter of `dayOfWeekAbbr` if `dayOfWeekShort` doesn't exist in the locale file
      var dayOfWeekShort = localeModel.get(['time', 'dayOfWeekShort']);
      nameMap = dayOfWeekShort || util.map(localeModel.get(['time', 'dayOfWeekAbbr']), function (val) {
        return val[0];
      });
    }
    var start = coordSys.getNextNDay(rangeData.end.time, 7 - rangeData.lweek).time;
    var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
    margin = number.parsePercent(margin, Math.min(cellSize[1], cellSize[0]));
    if (pos === 'start') {
      start = coordSys.getNextNDay(rangeData.start.time, -(7 + rangeData.fweek)).time;
      margin = -margin;
    }
    var labelSilent = dayLabel.get('silent');
    for (var i = 0; i < 7; i++) {
      var tmpD = coordSys.getNextNDay(start, i);
      var point = coordSys.dataToCalendarLayout([tmpD.time], false).center;
      var day = i;
      day = Math.abs((i + firstDayOfWeek) % 7);
      var weekText = new Text.default({
        z2: 30,
        style: util.extend(labelStyle.createTextStyle(dayLabel, {
          text: nameMap[day]
        }), this._weekTextPositionControl(point, orient, pos, margin, cellSize)),
        silent: labelSilent
      });
      group.add(weekText);
    }
  };
  CalendarView.type = 'calendar';
  return CalendarView;
}(Component.default);

exports.default = CalendarView;
