/*
* 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 layout from '../../util/layout';
import * as numberUtil from '../../util/number';
import BoundingRect, {RectLike} from 'zrender/src/core/BoundingRect';
import CalendarModel from './CalendarModel';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import {
    LayoutOrient,
    ScaleDataValue,
    OptionDataValueDate,
    SeriesOption,
    SeriesOnCalendarOptionMixin
} from '../../util/types';
import { ParsedModelFinder, ParsedModelFinderKnown } from '../../util/model';
import { CoordinateSystem, CoordinateSystemMaster } from '../CoordinateSystem';
import SeriesModel from '../../model/Series';

// (24*60*60*1000)
const PROXIMATE_ONE_DAY = 86400000;


export interface CalendarParsedDateRangeInfo {
    range: [string, string],
    start: CalendarParsedDateInfo
    end: CalendarParsedDateInfo
    allDay: number
    weeks: number
    nthWeek: number
    fweek: number
    lweek: number
}

export interface CalendarParsedDateInfo {
    /**
     * local full year, eg., '1940'
     */
    y: string
    /**
     * local month, from '01' ot '12',
     */
    m: string
    /**
     * local date, from '01' to '31' (if exists),
     */
    d: string
    /**
     * It is not date.getDay(). It is the location of the cell in a week, from 0 to 6,
     */
    day: number
    /**
     * Timestamp
     */
    time: number
    /**
     * yyyy-MM-dd
     */
    formatedDate: string
    /**
     * The original date object
     */
    date: Date
}

export interface CalendarCellRect {
    contentShape: RectLike
    center: number[]
    tl: number[]
    tr: number[]
    br: number[]
    bl: number[]
}

class Calendar implements CoordinateSystem, CoordinateSystemMaster {

    static readonly dimensions = ['time', 'value'];
    static getDimensionsInfo() {
        return [{
            name: 'time', type: 'time' as const
        }, 'value'];
    }

    readonly type = 'calendar';

    readonly dimensions = Calendar.dimensions;

    private _model: CalendarModel;

    private _rect: BoundingRect;

    private _sw: number;
    private _sh: number;
    private _orient: LayoutOrient;

    private _firstDayOfWeek: number;

    private _rangeInfo: CalendarParsedDateRangeInfo;

    private _lineWidth: number;

    constructor(calendarModel: CalendarModel, ecModel: GlobalModel, api: ExtensionAPI) {
        this._model = calendarModel;
    }
    // Required in createListFromData
    getDimensionsInfo = Calendar.getDimensionsInfo;

    getRangeInfo() {
        return this._rangeInfo;
    }

    getModel() {
        return this._model;
    }

    getRect() {
        return this._rect;
    }

    getCellWidth() {
        return this._sw;
    }

    getCellHeight() {
        return this._sh;
    }

    getOrient() {
        return this._orient;
    }

    /**
     * getFirstDayOfWeek
     *
     * @example
     *     0 : start at Sunday
     *     1 : start at Monday
     *
     * @return {number}
     */
    getFirstDayOfWeek() {
        return this._firstDayOfWeek;
    }

    /**
     * get date info
     * }
     */
    getDateInfo(date: OptionDataValueDate): CalendarParsedDateInfo {

        date = numberUtil.parseDate(date);

        const y = date.getFullYear();

        const m = date.getMonth() + 1;
        const mStr = m < 10 ? '0' + m : '' + m;

        const d = date.getDate();
        const dStr = d < 10 ? '0' + d : '' + d;

        let day = date.getDay();

        day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7);

        return {
            y: y + '',
            m: mStr,
            d: dStr,
            day: day,
            time: date.getTime(),
            formatedDate: y + '-' + mStr + '-' + dStr,
            date: date
        };
    }

    getNextNDay(date: OptionDataValueDate, n: number) {
        n = n || 0;
        if (n === 0) {
            return this.getDateInfo(date);
        }

        date = new Date(this.getDateInfo(date).time);
        date.setDate(date.getDate() + n);

        return this.getDateInfo(date);
    }

    update(ecModel: GlobalModel, api: ExtensionAPI) {

        this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay');
        this._orient = this._model.get('orient');
        this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0;


        this._rangeInfo = this._getRangeInfo(this._initRangeOption());
        const weeks = this._rangeInfo.weeks || 1;
        const whNames = ['width', 'height'] as const;
        const cellSize = this._model.getCellSize().slice();
        const layoutParams = this._model.getBoxLayoutParams();
        const cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks];

        zrUtil.each([0, 1] as const, function (idx) {
            if (cellSizeSpecified(cellSize, idx)) {
                layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx];
            }
        });

        const whGlobal = {
            width: api.getWidth(),
            height: api.getHeight()
        };
        const calendarRect = this._rect = layout.getLayoutRect(layoutParams, whGlobal);

        zrUtil.each([0, 1], function (idx) {
            if (!cellSizeSpecified(cellSize, idx)) {
                cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx];
            }
        });

        function cellSizeSpecified(cellSize: (number | 'auto')[], idx: number): cellSize is number[] {
            return cellSize[idx] != null && cellSize[idx] !== 'auto';
        }

        // Has been calculated out number.
        this._sw = cellSize[0] as number;
        this._sh = cellSize[1] as number;
    }


    /**
     * Convert a time data(time, value) item to (x, y) point.
     */
    // TODO Clamp of calendar is not same with cartesian coordinate systems.
    // It will return NaN if data exceeds.
    dataToPoint(data: OptionDataValueDate | OptionDataValueDate[], clamp?: boolean) {
        zrUtil.isArray(data) && (data = data[0]);
        clamp == null && (clamp = true);

        const dayInfo = this.getDateInfo(data);
        const range = this._rangeInfo;
        const date = dayInfo.formatedDate;

        // if not in range return [NaN, NaN]
        if (clamp && !(
            dayInfo.time >= range.start.time
            && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY
        )) {
            return [NaN, NaN];
        }

        const week = dayInfo.day;
        const nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek;

        if (this._orient === 'vertical') {
            return [
                this._rect.x + week * this._sw + this._sw / 2,
                this._rect.y + nthWeek * this._sh + this._sh / 2
            ];

        }

        return [
            this._rect.x + nthWeek * this._sw + this._sw / 2,
            this._rect.y + week * this._sh + this._sh / 2
        ];

    }

    /**
     * Convert a (x, y) point to time data
     */
    pointToData(point: number[]): number {

        const date = this.pointToDate(point);

        return date && date.time;
    }

    /**
     * Convert a time date item to (x, y) four point.
     */
    dataToRect(data: OptionDataValueDate | OptionDataValueDate[], clamp?: boolean): CalendarCellRect {
        const point = this.dataToPoint(data, clamp);

        return {
            contentShape: {
                x: point[0] - (this._sw - this._lineWidth) / 2,
                y: point[1] - (this._sh - this._lineWidth) / 2,
                width: this._sw - this._lineWidth,
                height: this._sh - this._lineWidth
            },

            center: point,

            tl: [
                point[0] - this._sw / 2,
                point[1] - this._sh / 2
            ],

            tr: [
                point[0] + this._sw / 2,
                point[1] - this._sh / 2
            ],

            br: [
                point[0] + this._sw / 2,
                point[1] + this._sh / 2
            ],

            bl: [
                point[0] - this._sw / 2,
                point[1] + this._sh / 2
            ]

        };
    }

    /**
     * Convert a (x, y) point to time date
     *
     * @param  {Array} point point
     * @return {Object}       date
     */
    pointToDate(point: number[]): CalendarParsedDateInfo {
        const nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1;
        const nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1;
        const range = this._rangeInfo.range;

        if (this._orient === 'vertical') {
            return this._getDateByWeeksAndDay(nthY, nthX - 1, range);
        }

        return this._getDateByWeeksAndDay(nthX, nthY - 1, range);
    }

    convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue | ScaleDataValue[]) {
        const coordSys = getCoordSys(finder);
        return coordSys === this ? coordSys.dataToPoint(value) : null;
    }

    convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) {
        const coordSys = getCoordSys(finder);
        return coordSys === this ? coordSys.pointToData(pixel) : null;
    }

    containPoint(point: number[]): boolean {
        console.warn('Not implemented.');
        return false;
    }

    /**
     * initRange
     * Normalize to an [start, end] array
     */
    private _initRangeOption(): OptionDataValueDate[] {
        let range = this._model.get('range');
        let normalizedRange: OptionDataValueDate[];

        // Convert [1990] to 1990
        if (zrUtil.isArray(range) && range.length === 1) {
            range = range[0];
        }

        if (!zrUtil.isArray(range)) {
            const rangeStr = range.toString();
            // One year.
            if (/^\d{4}$/.test(rangeStr)) {
                normalizedRange = [rangeStr + '-01-01', rangeStr + '-12-31'];
            }
            // One month
            if (/^\d{4}[\/|-]\d{1,2}$/.test(rangeStr)) {

                const start = this.getDateInfo(rangeStr);
                const firstDay = start.date;
                firstDay.setMonth(firstDay.getMonth() + 1);

                const end = this.getNextNDay(firstDay, -1);
                normalizedRange = [start.formatedDate, end.formatedDate];
            }
            // One day
            if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rangeStr)) {
                normalizedRange = [rangeStr, rangeStr];
            }
        }
        else {
            normalizedRange = range;
        }

        if (!normalizedRange) {
            if (__DEV__) {
                zrUtil.logError('Invalid date range.');
            }
            // Not handling it.
            return range as OptionDataValueDate[];
        }

        const tmp = this._getRangeInfo(normalizedRange);

        if (tmp.start.time > tmp.end.time) {
            normalizedRange.reverse();
        }

        return normalizedRange;
    }

    /**
     * range info
     *
     * @private
     * @param  {Array} range range ['2017-01-01', '2017-07-08']
     *  If range[0] > range[1], they will not be reversed.
     * @return {Object}       obj
     */
    _getRangeInfo(range: OptionDataValueDate[]): CalendarParsedDateRangeInfo {
        const parsedRange = [
            this.getDateInfo(range[0]),
            this.getDateInfo(range[1])
        ];

        let reversed;
        if (parsedRange[0].time > parsedRange[1].time) {
            reversed = true;
            parsedRange.reverse();
        }

        let allDay = Math.floor(parsedRange[1].time / PROXIMATE_ONE_DAY)
            - Math.floor(parsedRange[0].time / PROXIMATE_ONE_DAY) + 1;

        // Consider case1 (#11677 #10430):
        // Set the system timezone as "UK", set the range to `['2016-07-01', '2016-12-31']`

        // Consider case2:
        // Firstly set system timezone as "Time Zone: America/Toronto",
        // ```
        // let first = new Date(1478412000000 - 3600 * 1000 * 2.5);
        // let second = new Date(1478412000000);
        // let allDays = Math.floor(second / ONE_DAY) - Math.floor(first / ONE_DAY) + 1;
        // ```
        // will get wrong result because of DST. So we should fix it.
        const date = new Date(parsedRange[0].time);
        const startDateNum = date.getDate();
        const endDateNum = parsedRange[1].date.getDate();
        date.setDate(startDateNum + allDay - 1);
        // The bias can not over a month, so just compare date.
        let dateNum = date.getDate();
        if (dateNum !== endDateNum) {
            const sign = date.getTime() - parsedRange[1].time > 0 ? 1 : -1;
            while (
                (dateNum = date.getDate()) !== endDateNum
                && (date.getTime() - parsedRange[1].time) * sign > 0
            ) {
                allDay -= sign;
                date.setDate(dateNum - sign);
            }
        }

        const weeks = Math.floor((allDay + parsedRange[0].day + 6) / 7);
        const nthWeek = reversed ? -weeks + 1 : weeks - 1;

        reversed && parsedRange.reverse();

        return {
            range: [parsedRange[0].formatedDate, parsedRange[1].formatedDate],
            start: parsedRange[0],
            end: parsedRange[1],
            allDay: allDay,
            weeks: weeks,
            // From 0.
            nthWeek: nthWeek,
            fweek: parsedRange[0].day,
            lweek: parsedRange[1].day
        };
    }

    /**
     * get date by nthWeeks and week day in range
     *
     * @private
     * @param  {number} nthWeek the week
     * @param  {number} day   the week day
     * @param  {Array} range [d1, d2]
     * @return {Object}
     */
    private _getDateByWeeksAndDay(nthWeek: number, day: number, range: OptionDataValueDate[]): CalendarParsedDateInfo {
        const rangeInfo = this._getRangeInfo(range);

        if (nthWeek > rangeInfo.weeks
            || (nthWeek === 0 && day < rangeInfo.fweek)
            || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek)
        ) {
            return null;
        }

        const nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day;
        const date = new Date(rangeInfo.start.time);
        date.setDate(+rangeInfo.start.d + nthDay);

        return this.getDateInfo(date);
    }

    static create(ecModel: GlobalModel, api: ExtensionAPI) {
        const calendarList: Calendar[] = [];

        ecModel.eachComponent('calendar', function (calendarModel: CalendarModel) {
            const calendar = new Calendar(calendarModel, ecModel, api);
            calendarList.push(calendar);
            calendarModel.coordinateSystem = calendar;
        });

        ecModel.eachSeries(function (calendarSeries: SeriesModel<SeriesOption & SeriesOnCalendarOptionMixin>) {
            if (calendarSeries.get('coordinateSystem') === 'calendar') {
                // Inject coordinate system
                calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
            }
        });
        return calendarList;
    }
}

function getCoordSys(finder: ParsedModelFinderKnown): Calendar {
    const calendarModel = finder.calendarModel as CalendarModel;
    const seriesModel = finder.seriesModel;

    const coordSys = calendarModel
        ? calendarModel.coordinateSystem
        : seriesModel
        ? seriesModel.coordinateSystem
        : null;

    return coordSys as Calendar;
}

export default Calendar;
