/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as zrUtil from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import {createTextStyle} from '../../label/labelStyle';
import * as formatUtil from '../../util/format';
import * as numberUtil from '../../util/number';
import CalendarModel from '../../coord/calendar/CalendarModel';
import {CalendarParsedDateRangeInfo, CalendarParsedDateInfo} from '../../coord/calendar/Calendar';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { LayoutOrient, OptionDataValueDate, ZRTextAlign, ZRTextVerticalAlign } from '../../util/types';
import ComponentView from '../../view/Component';
import { PathStyleProps } from 'zrender/src/graphic/Path';
import { TextStyleProps, TextProps } from 'zrender/src/graphic/Text';

const MONTH_TEXT = {
    EN: [
        'Jan', 'Feb', 'Mar',
        'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep',
        'Oct', 'Nov', 'Dec'
    ],
    CN: [
        '一月', '二月', '三月',
        '四月', '五月', '六月',
        '七月', '八月', '九月',
        '十月', '十一月', '十二月'
    ]
};

const WEEK_TEXT = {
    EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    CN: ['日', '一', '二', '三', '四', '五', '六']
};

class CalendarView extends ComponentView {

    static type = 'calendar';
    type = CalendarView.type;

    /**
     * top/left line points
     */
    private _tlpoints: number[][];

    /**
     * bottom/right line points
     */
    private _blpoints: number[][];

    /**
     * first day of month
     */
    private _firstDayOfMonth: CalendarParsedDateInfo[];

    /**
     * first day point of month
     */
    private _firstDayPoints: number[][];

    render(calendarModel: CalendarModel, ecModel: GlobalModel, api: ExtensionAPI) {

        const group = this.group;

        group.removeAll();

        const coordSys = calendarModel.coordinateSystem;

        // range info
        const rangeData = coordSys.getRangeInfo();
        const orient = coordSys.getOrient();

        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, orient, group);

        this._renderWeekText(calendarModel, rangeData, orient, group);
    }

    // render day rect
    _renderDayRect(calendarModel: CalendarModel, rangeData: CalendarParsedDateRangeInfo, group: graphic.Group) {
        const coordSys = calendarModel.coordinateSystem;
        const itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle();
        const sw = coordSys.getCellWidth();
        const sh = coordSys.getCellHeight();

        for (let i = rangeData.start.time;
            i <= rangeData.end.time;
            i = coordSys.getNextNDay(i, 1).time
        ) {

            const point = coordSys.dataToRect([i], false).tl;

            // every rect
            const rect = new graphic.Rect({
                shape: {
                    x: point[0],
                    y: point[1],
                    width: sw,
                    height: sh
                },
                cursor: 'default',
                style: itemRectStyleModel
            });

            group.add(rect);
        }

    }

    // render separate line
    _renderLines(
        calendarModel: CalendarModel,
        rangeData: CalendarParsedDateRangeInfo,
        orient: LayoutOrient,
        group: graphic.Group
    ) {

        const self = this;

        const coordSys = calendarModel.coordinateSystem;

        const lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle();
        const show = calendarModel.get(['splitLine', 'show']);

        const lineWidth = lineStyleModel.lineWidth;

        this._tlpoints = [];
        this._blpoints = [];
        this._firstDayOfMonth = [];
        this._firstDayPoints = [];


        let firstDay = rangeData.start;

        for (let i = 0; firstDay.time <= rangeData.end.time; i++) {
            addPoints(firstDay.formatedDate);

            if (i === 0) {
                firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
            }

            const date = firstDay.date;
            date.setMonth(date.getMonth() + 1);
            firstDay = coordSys.getDateInfo(date);
        }

        addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);

        function addPoints(date: OptionDataValueDate) {

            self._firstDayOfMonth.push(coordSys.getDateInfo(date));
            self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);

            const 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
    _getEdgesPoints(points: number[][], lineWidth: number, orient: LayoutOrient) {
        const rs = [points[0].slice(), points[points.length - 1].slice()];
        const 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
    _drawSplitline(points: number[][], lineStyle: PathStyleProps, group: graphic.Group) {

        const poyline = new graphic.Polyline({
            z2: 20,
            shape: {
                points: points
            },
            style: lineStyle
        });

        group.add(poyline);
    }

    // render month line of one week points
    _getLinePointsOfOneWeek(calendarModel: CalendarModel, date: OptionDataValueDate, orient: LayoutOrient) {

        const coordSys = calendarModel.coordinateSystem;
        const parsedDate = coordSys.getDateInfo(date);

        const points = [];

        for (let i = 0; i < 7; i++) {

            const tmpD = coordSys.getNextNDay(parsedDate.time, i);
            const point = coordSys.dataToRect([tmpD.time], false);

            points[2 * tmpD.day] = point.tl;
            points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
        }

        return points;

    }

    _formatterLabel<T extends { nameMap: string }>(
        formatter: string | ((params: T) => string),
        params: T
    ) {

        if (typeof formatter === 'string' && formatter) {
            return formatUtil.formatTplSimple(formatter, params);
        }

        if (typeof formatter === 'function') {
            return formatter(params);
        }

        return params.nameMap;

    }

    _yearTextPositionControl(
        textEl: graphic.Text,
        point: number[],
        orient: LayoutOrient,
        position: 'left' | 'right' | 'top' | 'bottom',
        margin: number
    ): TextProps {

        let x = point[0];
        let y = point[1];
        let aligns: [ZRTextAlign, ZRTextVerticalAlign] = ['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;
        }

        let rotate = 0;
        if (position === 'left' || position === 'right') {
            rotate = Math.PI / 2;
        }

        return {
            rotation: rotate,
            x,
            y,
            style: {
                align: aligns[0],
                verticalAlign: aligns[1]
            }
        };
    }

    // render year
    _renderYearText(
        calendarModel: CalendarModel,
        rangeData: CalendarParsedDateRangeInfo,
        orient: LayoutOrient,
        group: graphic.Group
    ) {
        const yearLabel = calendarModel.getModel('yearLabel');

        if (!yearLabel.get('show')) {
            return;
        }

        const margin = yearLabel.get('margin');
        let pos = yearLabel.get('position');

        if (!pos) {
            pos = orient !== 'horizontal' ? 'top' : 'left';
        }

        const points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
        const xc = (points[0][0] + points[1][0]) / 2;
        const yc = (points[0][1] + points[1][1]) / 2;

        const idx = orient === 'horizontal' ? 0 : 1;

        const posPoints = {
            top: [xc, points[idx][1]],
            bottom: [xc, points[1 - idx][1]],
            left: [points[1 - idx][0], yc],
            right: [points[idx][0], yc]
        };

        let name = rangeData.start.y;

        if (+rangeData.end.y > +rangeData.start.y) {
            name = name + '-' + rangeData.end.y;
        }

        const formatter = yearLabel.get('formatter');

        const params = {
            start: rangeData.start.y,
            end: rangeData.end.y,
            nameMap: name
        };

        const content = this._formatterLabel(formatter, params);

        const yearText = new graphic.Text({
            z2: 30,
            style: createTextStyle(yearLabel, {
                text: content
            })
        });
        yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));

        group.add(yearText);
    }

    _monthTextPositionControl(
        point: number[],
        isCenter: boolean,
        orient: LayoutOrient,
        position: 'start' | 'end',
        margin: number
    ): TextStyleProps {
        let align: ZRTextAlign = 'left';
        let vAlign: ZRTextVerticalAlign = 'top';
        let x = point[0];
        let 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
    _renderMonthText(calendarModel: CalendarModel, orient: LayoutOrient, group: graphic.Group) {
        const monthLabel = calendarModel.getModel('monthLabel');

        if (!monthLabel.get('show')) {
            return;
        }

        let nameMap = monthLabel.get('nameMap');
        let margin = monthLabel.get('margin');
        const pos = monthLabel.get('position');
        const align = monthLabel.get('align');

        const termPoints = [this._tlpoints, this._blpoints];

        if (zrUtil.isString(nameMap)) {
            nameMap = MONTH_TEXT[nameMap.toUpperCase() as 'CN' | 'EN'] || [];
        }

        const idx = pos === 'start' ? 0 : 1;
        const axis = orient === 'horizontal' ? 0 : 1;
        margin = pos === 'start' ? -margin : margin;
        const isCenter = (align === 'center');

        for (let i = 0; i < termPoints[idx].length - 1; i++) {

            const tmp = termPoints[idx][i].slice();
            const firstDay = this._firstDayOfMonth[i];

            if (isCenter) {
                const firstDayPoints = this._firstDayPoints[i];
                tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
            }

            const formatter = monthLabel.get('formatter');
            const name = nameMap[+firstDay.m - 1];
            const params = {
                yyyy: firstDay.y,
                yy: (firstDay.y + '').slice(2),
                MM: firstDay.m,
                M: +firstDay.m,
                nameMap: name
            };

            const content = this._formatterLabel(formatter, params);

            const monthText = new graphic.Text({
                z2: 30,
                style: zrUtil.extend(
                    createTextStyle(monthLabel, {text: content}),
                    this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)
                )
            });

            group.add(monthText);
        }
    }

    _weekTextPositionControl(
        point: number[],
        orient: LayoutOrient,
        position: 'start' | 'end',
        margin: number,
        cellSize: number[]
    ): TextStyleProps {
        let align: ZRTextAlign = 'center';
        let vAlign: ZRTextVerticalAlign = 'middle';
        let x = point[0];
        let y = point[1];
        const 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
    _renderWeekText(
        calendarModel: CalendarModel,
        rangeData: CalendarParsedDateRangeInfo,
        orient: LayoutOrient,
        group: graphic.Group
    ) {
        const dayLabel = calendarModel.getModel('dayLabel');

        if (!dayLabel.get('show')) {
            return;
        }

        const coordSys = calendarModel.coordinateSystem;
        const pos = dayLabel.get('position');
        let nameMap = dayLabel.get('nameMap');
        let margin = dayLabel.get('margin');
        const firstDayOfWeek = coordSys.getFirstDayOfWeek();

        if (zrUtil.isString(nameMap)) {
            nameMap = WEEK_TEXT[nameMap.toUpperCase() as 'CN' | 'EN'] || [];
        }

        let start = coordSys.getNextNDay(
            rangeData.end.time, (7 - rangeData.lweek)
        ).time;

        const cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
        margin = numberUtil.parsePercent(margin, Math.min(cellSize[1], cellSize[0]));

        if (pos === 'start') {
            start = coordSys.getNextNDay(
                rangeData.start.time, -(7 + rangeData.fweek)
            ).time;
            margin = -margin;
        }

        for (let i = 0; i < 7; i++) {

            const tmpD = coordSys.getNextNDay(start, i);
            const point = coordSys.dataToRect([tmpD.time], false).center;
            let day = i;
            day = Math.abs((i + firstDayOfWeek) % 7);
            const weekText = new graphic.Text({
                z2: 30,
                style: zrUtil.extend(
                    createTextStyle(dayLabel, {text: nameMap[day]}),
                    this._weekTextPositionControl(point, orient, pos, margin, cellSize)
                )
            });

            group.add(weekText);
        }
    }
}

export default CalendarView;