/*
* 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 Model from './Model';
import * as componentUtil from '../util/component';
import {
    enableClassManagement,
    parseClassType,
    isExtendedClass,
    ExtendableConstructor,
    ClassManager,
    mountExtend
} from '../util/clazz';
import {
    makeInner, ModelFinderIndexQuery, queryReferringComponents, ModelFinderIdQuery, QueryReferringOpt
} from '../util/model';
import * as layout from '../util/layout';
import GlobalModel from './Global';
import {
    ComponentOption,
    ComponentMainType,
    ComponentSubType,
    ComponentFullType,
    ComponentLayoutMode,
    BoxLayoutOptionMixin
} from '../util/types';

const inner = makeInner<{
    defaultOption: ComponentOption
}, ComponentModel>();


class ComponentModel<Opt extends ComponentOption = ComponentOption> extends Model<Opt> {

    // [Caution]: Becuase this class or desecendants can be used as `XXX.extend(subProto)`,
    // the class members must not be initialized in constructor or declaration place.
    // Otherwise there is bad case:
    //   class A {xxx = 1;}
    //   enableClassExtend(A);
    //   class B extends A {}
    //   var C = B.extend({xxx: 5});
    //   var c = new C();
    //   console.log(c.xxx); // expect 5 but always 1.

    /**
     * @readonly
     */
    type: ComponentFullType;

    /**
     * @readonly
     */
    id: string;

    /**
     * Because simplified concept is probably better, series.name (or component.name)
     * has been having too many resposibilities:
     * (1) Generating id (which requires name in option should not be modified).
     * (2) As an index to mapping series when merging option or calling API (a name
     * can refer to more then one components, which is convinient is some case).
     * (3) Display.
     * @readOnly But injected
     */
    name: string;

    /**
     * @readOnly
     */
    mainType: ComponentMainType;

    /**
     * @readOnly
     */
    subType: ComponentSubType;

    /**
     * @readOnly
     */
    componentIndex: number;

    /**
     * @readOnly
     */
    protected defaultOption: ComponentOption;

    /**
     * @readOnly
     */
    ecModel: GlobalModel;

    /**
     * @readOnly
     */
    static dependencies: string[];


    readonly uid: string;

    // // No common coordinateSystem needed. Each sub class implement
    // // `CoordinateSystemHostModel` itself.
    // coordinateSystem: CoordinateSystemMaster | CoordinateSystemExecutive;

    /**
     * Support merge layout params.
     * Only support 'box' now (left/right/top/bottom/width/height).
     */
    static layoutMode: ComponentLayoutMode | ComponentLayoutMode['type'];

    /**
     * Prevent from auto set z, zlevel, z2 by the framework.
     */
    preventAutoZ: boolean;

    // Injectable properties:
    __viewId: string;
    __requireNewView: boolean;

    static protoInitialize = (function () {
        const proto = ComponentModel.prototype;
        proto.type = 'component';
        proto.id = '';
        proto.name = '';
        proto.mainType = '';
        proto.subType = '';
        proto.componentIndex = 0;
    })();


    constructor(option: Opt, parentModel: Model, ecModel: GlobalModel) {
        super(option, parentModel, ecModel);
        this.uid = componentUtil.getUID('ec_cpt_model');
    }

    init(option: Opt, parentModel: Model, ecModel: GlobalModel): void {
        this.mergeDefaultAndTheme(option, ecModel);
    }

    mergeDefaultAndTheme(option: Opt, ecModel: GlobalModel): void {
        const layoutMode = layout.fetchLayoutMode(this);
        const inputPositionParams = layoutMode
            ? layout.getLayoutParams(option as BoxLayoutOptionMixin) : {};

        const themeModel = ecModel.getTheme();
        zrUtil.merge(option, themeModel.get(this.mainType));
        zrUtil.merge(option, this.getDefaultOption());

        if (layoutMode) {
            layout.mergeLayoutParam(option as BoxLayoutOptionMixin, inputPositionParams, layoutMode);
        }
    }

    mergeOption(option: Opt, ecModel: GlobalModel): void {
        zrUtil.merge(this.option, option, true);

        const layoutMode = layout.fetchLayoutMode(this);
        if (layoutMode) {
            layout.mergeLayoutParam(
                this.option as BoxLayoutOptionMixin,
                option as BoxLayoutOptionMixin,
                layoutMode
            );
        }
    }

    /**
     * Called immediately after `init` or `mergeOption` of this instance called.
     */
    optionUpdated(newCptOption: Opt, isInit: boolean): void {}

    /**
     * [How to declare defaultOption]:
     *
     * (A) If using class declaration in typescript (since echarts 5):
     * ```ts
     * import {ComponentOption} from '../model/option';
     * export interface XxxOption extends ComponentOption {
     *     aaa: number
     * }
     * export class XxxModel extends Component {
     *     static type = 'xxx';
     *     static defaultOption: XxxOption = {
     *         aaa: 123
     *     }
     * }
     * Component.registerClass(XxxModel);
     * ```
     * ```ts
     * import {inheritDefaultOption} from '../util/component';
     * import {XxxModel, XxxOption} from './XxxModel';
     * export interface XxxSubOption extends XxxOption {
     *     bbb: number
     * }
     * class XxxSubModel extends XxxModel {
     *     static defaultOption: XxxSubOption = inheritDefaultOption(XxxModel.defaultOption, {
     *         bbb: 456
     *     })
     *     fn() {
     *         let opt = this.getDefaultOption();
     *         // opt is {aaa: 123, bbb: 456}
     *     }
     * }
     * ```
     *
     * (B) If using class extend (previous approach in echarts 3 & 4):
     * ```js
     * let XxxComponent = Component.extend({
     *     defaultOption: {
     *         xx: 123
     *     }
     * })
     * ```
     * ```js
     * let XxxSubComponent = XxxComponent.extend({
     *     defaultOption: {
     *         yy: 456
     *     },
     *     fn: function () {
     *         let opt = this.getDefaultOption();
     *         // opt is {xx: 123, yy: 456}
     *     }
     * })
     * ```
     */
    getDefaultOption(): Opt {
        const ctor = this.constructor;

        // If using class declaration, it is different to travel super class
        // in legacy env and auto merge defaultOption. So if using class
        // declaration, defaultOption should be merged manually.
        if (!isExtendedClass(ctor)) {
            // When using ts class, defaultOption must be declared as static.
            return (ctor as any).defaultOption;
        }

        // FIXME: remove this approach?
        const fields = inner(this);
        if (!fields.defaultOption) {
            const optList = [];
            let clz = ctor as ExtendableConstructor;
            while (clz) {
                const opt = clz.prototype.defaultOption;
                opt && optList.push(opt);
                clz = clz.superClass;
            }

            let defaultOption = {};
            for (let i = optList.length - 1; i >= 0; i--) {
                defaultOption = zrUtil.merge(defaultOption, optList[i], true);
            }
            fields.defaultOption = defaultOption;
        }
        return fields.defaultOption as Opt;
    }

    /**
     * Notice: always force to input param `useDefault` in case that forget to consider it.
     * The same behavior as `modelUtil.parseFinder`.
     *
     * @param useDefault In many cases like series refer axis and axis refer grid,
     *        If axis index / axis id not specified, use the first target as default.
     *        In other cases like dataZoom refer axis, if not specified, measn no refer.
     */
    getReferringComponents(mainType: ComponentMainType, opt: QueryReferringOpt): {
        // Always be array rather than null/undefined, which is convenient to use.
        models: ComponentModel[];
        // Whether target compoent specified
        specified: boolean;
    } {
        const indexKey = (mainType + 'Index') as keyof Opt;
        const idKey = (mainType + 'Id') as keyof Opt;

        return queryReferringComponents(
            this.ecModel,
            mainType,
            {
                index: this.get(indexKey, true) as unknown as ModelFinderIndexQuery,
                id: this.get(idKey, true) as unknown as ModelFinderIdQuery
            },
            opt
        );
    }

    getBoxLayoutParams() {
        // Consider itself having box layout configs.
        const boxLayoutModel = this as Model<ComponentOption & BoxLayoutOptionMixin>;
        return {
            left: boxLayoutModel.get('left'),
            top: boxLayoutModel.get('top'),
            right: boxLayoutModel.get('right'),
            bottom: boxLayoutModel.get('bottom'),
            width: boxLayoutModel.get('width'),
            height: boxLayoutModel.get('height')
        };
    }

    // // Interfaces for component / series with select ability.
    // select(dataIndex?: number[], dataType?: string): void {}

    // unSelect(dataIndex?: number[], dataType?: string): void {}

    // getSelectedDataIndices(): number[] {
    //     return [];
    // }


    static registerClass: ClassManager['registerClass'];

    static hasClass: ClassManager['hasClass'];

    static registerSubTypeDefaulter: componentUtil.SubTypeDefaulterManager['registerSubTypeDefaulter'];

}

export type ComponentModelConstructor = typeof ComponentModel
    & ClassManager
    & componentUtil.SubTypeDefaulterManager
    & ExtendableConstructor
    & componentUtil.TopologicalTravelable<object>;

mountExtend(ComponentModel, Model);
enableClassManagement(ComponentModel as ComponentModelConstructor);
componentUtil.enableSubTypeDefaulter(ComponentModel as ComponentModelConstructor);
componentUtil.enableTopologicalTravel(ComponentModel as ComponentModelConstructor, getDependencies);


function getDependencies(componentType: string): string[] {
    let deps: string[] = [];
    zrUtil.each((ComponentModel as ComponentModelConstructor).getClassesByMainType(componentType), function (clz) {
        deps = deps.concat((clz as any).dependencies || (clz as any).prototype.dependencies || []);
    });

    // Ensure main type.
    deps = zrUtil.map(deps, function (type) {
        return parseClassType(type).main;
    });

    // Hack dataset for convenience.
    if (componentType !== 'dataset' && zrUtil.indexOf(deps, 'dataset') <= 0) {
        deps.unshift('dataset');
    }

    return deps;
}


export default ComponentModel;
