import { Prop, Watch, Emit } from 'vue-property-decorator';
import {
    Util,
    LayoutTool,
    throttle,
} from 'ibiz-core';
import { SearchFormControlBase } from '../../../widgets';
import { IPSAppDEUIAction, IPSDEFormButton, IPSDEFormDetail, IPSDEFormDRUIPart, IPSDEFormFormPart, IPSDEFormGroupPanel, IPSDEFormIFrame, IPSDEFormPage, IPSDEFormRawItem, IPSDEFormTabPage, IPSDEFormTabPanel, IPSDESearchFormItem, IPSEditor, IPSFlexLayout, IPSFlexLayoutPos, IPSGridLayoutPos, IPSLayout, IPSLanguageRes } from '@ibiz/dynamic-model-api';

/**
 * 搜索表单部件基类
 *
 * @export
 * @class AppSearchFormBase
 * @extends {SearchFormControlBase}
 */
export class AppSearchFormBase extends SearchFormControlBase {

    /**
     * 部件静态参数
     *
     * @memberof AppSearchFormBase
     */
    @Prop() public declare staticProps: any;

    /**
     * 部件动态参数
     *
     * @memberof AppSearchFormBase
     */
    @Prop() public declare dynamicProps: any;

    /**
     * 监听动态参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppSearchFormBase
     */
    @Watch('dynamicProps', {
        immediate: true,
    })
    public onDynamicPropsChange(newVal: any, oldVal: any) {
        if (newVal && !Util.isFieldsSame(newVal, oldVal)) {
            super.onDynamicPropsChange(newVal, oldVal);
        }
    }

    /**
     * 监听静态参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppSearchFormBase
     */
    @Watch('staticProps', {
        immediate: true,
    })
    public onStaticPropsChange(newVal: any, oldVal: any) {
        if (newVal && !Util.isFieldsSame(newVal, oldVal)) {
            super.onStaticPropsChange(newVal, oldVal);
        }
    }

    /**
     * 部件事件
     *
     * @param {{ controlname: string; action: string; data: any }} { controlname 部件名称, action 事件名称, data 事件参数 }
     * @memberof AppSearchFormBase
     */
    @Emit('ctrl-event')
    public ctrlEvent({ controlname, action, data }: { controlname: string; action: string; data: any }): void { }

    /**
     * 绘制子表单成员,布局控制
     *
     * @param {*} modelJson
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderDetails(modelJson: any) {
        let formDetails: IPSDEFormDetail[] = modelJson.getPSDEFormDetails();
        let layout: IPSLayout = modelJson.getPSLayout();
        // 没有子表单成员
        if (!formDetails || formDetails.length == 0) {
            return null;
        }

        // 无布局
        if (!layout) {
            return formDetails.map((item: any, index: number) => {
                return this.renderByDetailType(item, index);
            });
        }

        // 栅格布局
        if (layout.layout == 'TABLE_24COL' || layout.layout == 'TABLE_12COL') {
            return (
                <row>
                    {formDetails.map((item: IPSDEFormDetail, index: number) => {
                        if ((item as any).hidden) {
                            return
                        }
                        let attrs = LayoutTool.getGridOptions(item.getPSLayoutPos() as IPSGridLayoutPos);
                        return <i-col class='form-layout-container' {...{ props: attrs }} style={this.detailsModel[item.name]?.visible ? '' : 'display: none;'}>{this.renderByDetailType(item, index)}</i-col>;
                    })}
                </row>
            );
        }

        // FLEX布局
        if (layout.layout == 'FLEX') {
            const flexStyle = LayoutTool.getFlexStyle(layout as IPSFlexLayout);
            return (
                <div style={flexStyle}>
                    {formDetails.map((item: IPSDEFormDetail, index: number) => {
                         if ((item as any).hidden) {
                            return
                        }
                        let detailStyle =  LayoutTool.getFlexStyle2(item?.getPSLayoutPos() as IPSFlexLayoutPos);
                        detailStyle += this.detailsModel[item.name].visible ? '' : 'display: none;'
                        return <div style={detailStyle} class='form-layout-container'>{this.renderByDetailType(item, index)}</div>;
                    })}
                </div>
            );
        }
    }

    /**
     * 根据detailType绘制对应detail
     *
     * @param {*} modelJson
     * @param {number} index
     * @memberof AppSearchFormBase
     */
    public renderByDetailType(modelJson: IPSDEFormDetail, index: number) {
        if (modelJson.getPSSysPFPlugin()) {
            const pluginInstance: any = this.PluginFactory.getPluginInstance("CONTROLITEM", modelJson.getPSSysPFPlugin()?.pluginCode || '');
            if (pluginInstance) {
                return pluginInstance.renderCtrlItem(this.$createElement, modelJson, this, null);
            }
        } else {
            switch (modelJson.detailType) {
                case 'FORMPAGE':
                    return this.renderFormPage(modelJson as IPSDEFormPage, index);
                case 'GROUPPANEL':
                    return this.renderGroupPanel(modelJson as IPSDEFormGroupPanel, index);
                case 'TABPAGE':
                    return this.renderTabPage(modelJson as IPSDEFormTabPage, index);
                case 'TABPANEL':
                    return this.renderTabPanel(modelJson as IPSDEFormTabPanel, index);
                case 'FORMITEM':
                    return this.renderFormItem(modelJson as IPSDESearchFormItem, index);
                case 'BUTTON':
                    return this.renderButton(modelJson as IPSDEFormButton, index);
                case 'DRUIPART':
                    return this.renderDruipart(modelJson as IPSDEFormDRUIPart, index);
                case 'RAWITEM':
                    return this.renderRawitem(modelJson as IPSDEFormRawItem, index);
                case 'IFRAME':
                    return this.renderIframe(modelJson as IPSDEFormIFrame, index);
                case 'FORMPART':
                    return this.renderFormPart(modelJson as IPSDEFormFormPart, index);
            }
        }
    }

    /**
     * 绘制表单部件
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderFormPart(modelJson: IPSDEFormFormPart, index: number): any {
        let { formPartType, name, codeName } = modelJson;

        // 后续补
        let systemCodeName = '',
            appCodeName = '',
            deCodeName = '',
            formCodeName = '';

        if (formPartType && formPartType == 'DYNASYS') {
            return (
                <app-form-part
                    name={name}
                    context={this.context}
                    viewparams={this.viewparams}
                    formState={this.formState}
                    systemCodeName={systemCodeName}
                    appCodeName={appCodeName}
                    deCodeName={deCodeName}
                    formCodeName={formCodeName}
                    formDetailCodeName={codeName}
                    on-change={this.onFormItemValueChange}
                ></app-form-part>
            );
        }
    }

    /**
     * 绘制iframe
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderIframe(modelJson: any, index: number): any {
        let { contentHeight, iFrameUrl } = modelJson;
        let iframeStyle = { height: contentHeight + 'px' };
        return (
            <div style={iframeStyle}>
                <iframe src={iFrameUrl}></iframe>
            </div>
        );
    }

    /**
     * 绘制直接内容
     *
     * @returns
     * @memberof AppSearchFormBaseBase
     */
    public renderRawitem(modelJson: IPSDEFormRawItem, index: number): any {
        const data: any = this.data;
        let { rawItemHeight, rawItemWidth, contentType, htmlContent, rawContent } = modelJson;
        let sysCssName = modelJson.getPSSysCss()?.cssName;
        let sysImage = modelJson.getPSSysImage()?.cssClass;
        let sysImgurl = modelJson.getPSSysImage()?.imagePath;
        const style: any = {
            width: rawItemWidth > 0 ? `${rawItemWidth}px` : false,
            height: rawItemHeight > 0 ? `${rawItemHeight}px` :false,
        }
        let content: any;
        if (Object.is(contentType,'RAW')) {
            content = rawContent;
        } else if (Object.is(contentType,'HTML')){
            content = htmlContent;
        }
        if (content) {
            const items = content.match(/\{{(.+?)\}}/g);
            if (items) {
                items.forEach((item: string) => {
                    content = content.replace(/\{{(.+?)\}}/, eval(item.substring(2, item.length - 2)));
                });
            }
            content = content.replaceAll('&lt;','<');
            content = content.replaceAll('&gt;','>');
            content = content.replaceAll('&amp;nbsp;',' ');
            content = content.replaceAll('&nbsp;',' ');
        }
        return (
            <app-rawitem
                class={sysCssName}
                style={style}
                viewparams={this.viewparams}
                context={this.context}
                contentType={contentType}
                imageClass={sysImage}
                imgUrl={sysImgurl}
                content={content}
            >
            </app-rawitem>
        );
    }

    /**
     * 关系界面保存事件
     *
     * @param {*} e
     * @memberof AppSearchFormBase
     */
    public onDrDataSaved(e: any) {
        this.ctrlEvent({
            controlname: this.controlInstance.name,
            action: 'drdatasaved',
            data: e,
        });
    }

    /**
     * 绘制关系界面
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderDruipart(modelJson: any, index: number): any {
        const { getPSSysCss, refreshItems, getLayoutPos, contentHeight, appView, parentdata, localContext, localParam, appDERSPaths } = modelJson;
        const { dynaModelFilePath } = appView;
        let tempContext: any = Object.assign(this.context, { viewpath: dynaModelFilePath });
        // druipart样式
        let druipartHeight: any;
        if (getLayoutPos?.layout == 'FlEX') {
            druipartHeight = '100%';
        } else if (contentHeight === 0 && appView?.height > 0) {
            druipartHeight = appView.height;
        } else {
            druipartHeight = contentHeight;
        }
        let druipartStyle = { height: druipartHeight, overflow: 'auto' };
        return (
            <app-form-druipart
                class={getPSSysCss?.cssName}
                formState={this.formState}
                isForbidLoad={this.data?.srfuf === '0'}
                paramItem={this.appDeCodeName.toLowerCase()}
                parentdata={parentdata}
                parameters={Util.formatAppDERSPath(this.context, appDERSPaths)}
                context={tempContext}
                viewparams={this.viewparams}
                parameterName={this.appDeCodeName.toLowerCase()}
                parentName={this.appDeCodeName}
                appViewtype={appView?.viewType}
                refreshitems={refreshItems}
                ignorefieldvaluechange={this.ignorefieldvaluechange}
                viewname={'app-view-shell'}
                localContext={Util.formatNavParam(localContext)}
                localParam={Util.formatNavParam(localParam)}
                tempMode={appView?.tempMode ? appView?.tempMode : 0}
                data={JSON.stringify(this.data)}
                on-drdatasaved={($event: any)=>this.drdatasaved($event)}
                style={druipartStyle}
            ></app-form-druipart>
        );
    }

    /**
     * 绘制按钮
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderButton(modelJson: IPSDEFormButton, index: number): any {
        let dynaStyle:string = this.detailsModel[modelJson.name].visible ? '' :  'display:none';
        // 自定义类名
        const dynaClass: string = 'app-form-button';        
        let badge = null;
        // TODO计数器徽章
        // if (uiAction) {
        //     let { appCounter, counterId } = uiAction;
        //     let { codeName } = appCounter;
        //     let count = codeName + 'counterservice.counterData.' + counterId;
        //     badge = <badge type='primary' count={count}></badge>;
        // }
        return (
            <div>
                {badge}
                <app-model-button
                    modelJson={modelJson}
                    dynaStyle={dynaStyle}
                    dynaClass={dynaClass}
                    dynaType='primary'
                    disabled={this.detailsModel[modelJson.name]?.disabled}
                    on-onClick={($event: any) => throttle(this.onFormItemActionClick,[{formdetail:modelJson, event: $event }],this)}
                >
                </app-model-button>                
            </div>
        );
    }

    /**
     * 绘制表单项
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderFormItem(modelJson: IPSDESearchFormItem, index: number): any {
        const editor = modelJson.getPSEditor() as IPSEditor;
        return (
            <app-default-search-form-item
                detailsInstance={modelJson}
                modelService={this.modelService}
                index={index}
                data={this.data}
                rules={this.rules[modelJson.name]}
                runtimeModel={this.detailsModel[modelJson.name]}
                context={Util.deepCopy(this.context)}
                viewparams={Util.deepCopy(this.viewparams)}
                contextState={this.formState}
                service={this.service}
                ignorefieldvaluechange={this.ignorefieldvaluechange}
                on-formItemValueChange={(value: any) => {
                    this.onFormItemValueChange(value);
                }}
                controlInstance={this.controlInstance}
            >
                {editor && (
                    <app-default-editor
                        editorInstance={editor}
                        containerCtrl={this.controlInstance}
                        parentItem={modelJson}
                        value={this.data[editor?.name]}
                        contextData={this.data}
                        context={Util.deepCopy(this.context)}
                        viewparams={Util.deepCopy(this.viewparams)}
                        contextState={this.formState}
                        service={this.service}
                        disabled={this.detailsModel[modelJson.name]?.disabled}
                        ignorefieldvaluechange={this.ignorefieldvaluechange}
                        on-change={(value: any) => {
                            this.onFormItemValueChange(value);
                        }}
                    />
                )}
            </app-default-search-form-item>
        );
    }

    /**
     * 绘制分页部件panel
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderTabPanel(modelJson: any, index: number): any {
        return (
            <app-default-search-form-tab-panel
                modelService={this.modelService}
                detailsInstance={modelJson}
                index={index}
                controlInstance={this.controlInstance}>
                { this.renderDetails(modelJson)}
            </app-default-search-form-tab-panel>
        )
    }

    /**
     * 绘制分页部件
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderTabPage(modelJson: IPSDEFormTabPage, index: number): any {
        return (
            <app-default-search-form-tab-page
                modelService={this.modelService}
                detailsInstance={modelJson}
                index={index}
                controlInstance={this.controlInstance}>
                { this.renderDetails(modelJson)}
            </app-default-search-form-tab-page>
        );
    }

    /**
     * 绘制分组面板
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderGroupPanel(modelJson: IPSDEFormGroupPanel, index: number): any {
        return (
            <app-default-group-panel
                modelService={this.modelService}
                detailsInstance={modelJson}
                index={index}
                runtimeModel={this.detailsModel[modelJson.name]}
                controlInstance={this.controlInstance}
                on-groupUIActionClick={(...params: any[]) => throttle(this.handleActionClick,params,this)}
                data={this.data}
            >
                {this.renderDetails(modelJson)}
            </app-default-group-panel>
        );
    }

    /**
     * 绘制表单分页
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderFormPage(modelJson: IPSDEFormPage, index: number): any {
        const { noTabHeader } = this.controlInstance;
        if (noTabHeader) {
            return this.renderDetails(modelJson);
        }
        return (
            <app-default-search-form-page
                modelService={this.modelService}
                detailsInstance={modelJson}
                index={index}
                runtimeModel={this.detailsModel[modelJson.name]}
                controlInstance={this.controlInstance}
            >
                {this.renderDetails(modelJson)}
            </app-default-search-form-page>
        );
    }

    /**
     * 绘制表单内容
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public renderFormContent() {
        const { noTabHeader, codeName, name, controlType } = this.controlInstance;
        const formPages = this.controlInstance.getPSDEFormPages();
        if (formPages && formPages.length > 0) {
            if (noTabHeader) {
                return formPages.map((item: any, index: number) => {
                    return this.renderFormPage(item, index);
                });
            } else {
                const tabsName = `${this.appDeCodeName.toLowerCase()}_${controlType?.toLowerCase()}_${codeName?.toLowerCase()}`;
                return (
                    <tabs animated={false} name={tabsName}
                        value={this.detailsModel[name]?.activatedPage}
                        on-on-click={(e: any) => {
                          throttle(this.detailsModel[name]?.clickPage,[e],this);
                        }}
                    >
                        {formPages.map((item: any, index: number) => {
                            return this.renderFormPage(item, index);
                        })}
                    </tabs>
                );
            }
        }
    }

    /**
     * 获取搜索内容或按钮样式
     * 
     * @param position 位置
     * @memberof AppSearchFormBase
     */
    public getColStyle(position: string = 'content') {
        const { searchButtonStyle, searchButtonPos } = this.controlInstance as any;
        if (searchButtonPos && searchButtonPos == 'RIGHT') {
            switch (searchButtonStyle) {
                case 'DEFAULT':
                    if (this.enableSaveFilter) {
                        return position == 'content' ? { width: 'calc(100% - 220px)' } : { width: '220px' };
                    } else {
                        return position == 'content' ? { width: 'calc(100% - 138px' } : { width: '138px' };
                    }
                case 'SEARCHONLY':
                    return position == 'content' ? { width: 'calc(100% - 88px)' } : { width: '88px' };
                case 'NONE':
                    return position == 'content' ? { width: '100%' } : { };
            }
        } else {
            return {};
        }
    }


    /**
     * 绘制内容
     *
     * @returns
     * @memberof AppSearchFormBase
     */
    public render(): any {
        const isShow = this.controlInstance.formStyle != 'SEARCHBAR' ? this.isExpandSearchForm : true;
        if (!(this.controlIsLoaded && isShow)) {
            return
        }
        const { controlClassNames } = this.renderOptions;
        let formId = this.appDeCodeName.toLowerCase() + this.controlInstance.codeName?.toLowerCase();
        if (!this.controlInstance.getPSDEFormItems() || this.controlInstance.getPSDEFormItems()?.length == 0) {
            return null;
        }
        const { searchButtonStyle, searchButtonPos } = this.controlInstance as any;
        return (
            <i-form
                props={{ model: this.data }}
                class={{ 
                    ...controlClassNames,
                    'app-search-form': true,
                    'no-search-action': this.controlInstance.formStyle != 'SEARCHBAR' && searchButtonStyle != 'NONE' ? false : true,
                    [`${searchButtonPos && searchButtonPos == 'RIGHT' ? 'right' : 'bottom'}-button`]: true
                }}
                ref={this.controlInstance.name}
                id={formId}
                on-on-valuidate={this.formItemValidate.bind(this)}
                nativeOnkeyup={this.onKeyUp.bind(this)}
            >
                <input style='display:none;' />
                <row>
                    <i-col style={this.getColStyle()} class="form-content">
                        <row>
                            {this.renderFormContent()}
                        </row>
                    </i-col>
                {this.controlInstance.formStyle != 'SEARCHBAR' && searchButtonStyle != 'NONE' &&
                    <i-col
                        style={this.getColStyle('button')}
                        class="search-action-footer">
                        {this.historyItems?.length>0 ? 
                        <el-select
                            size="small"
                            popper-class="search-action-select"
                            value={this.selectItem}
                            on-change={this.onFilterChange.bind(this)}>
                                {this.historyItems.map((item: any)=> {
                                    return (
                                        <el-option
                                            key={item.value}
                                            label={item.name}
                                            value={item.value}
                                            >
                                                <div class="searchform-action-item" on-click={() => { if (this.selectItem == item.value) { this.data = JSON.parse(JSON.stringify(item.data)); } }}>
                                                    <span title={item.name}>{item.name}</span>
                                                    <i class="el-icon-close" on-click={(e: any) => throttle(this.removeHistoryItem,[e, item],this)}/>
                                                </div>
                                            </el-option>
                                    )
                                })}
                            </el-select> : null}
                        {Object.keys(this.data).length > 0 && <row class='search-button'>
                            {  searchButtonStyle == 'DEFAULT' || searchButtonStyle == 'SEARCHONLY' ? 
                                <i-button class='search_reset' size='default' type='primary' on-click={(...params: any[]) => throttle(this.search,params,this)}>{this.$t('app.searchbutton.search')}</i-button> : null }
                            { searchButtonStyle == 'DEFAULT' ? 
                             <i-button class='search_reset reset' size='default' on-click={(...params: any[]) => throttle(this.reset,params,this)}>{this.$t('app.searchbutton.reset')}</i-button> : null }
                            {this.enableSaveFilter && searchButtonStyle == 'DEFAULT' ?
                                <poptip
                                    ref="propip"
                                    trigger="hover"
                                    placement="top-end"
                                    title="存储自定义查询"
                                    popper-class="searchform-poptip"
                                    transfer
                                    on-on-popper-show={() => this.saveItemName = ''}>
                                        <i-button class="save-button"><i class="fa fa-floppy-o" aria-hidden="true"></i></i-button>
                                        <div slot="content">
                                            <i-input v-model={this.saveItemName} placeholder=""></i-input>
                                            <div class="save-action">
                                                <i-button on-click={(...params: any[]) => throttle(this.onCancel,params,this)}>{this.$t('app.commonwords.cancel')}</i-button>
                                                <i-button type="primary" on-click={(...params: any[]) => throttle(this.onOk,params,this)}>{this.$t('app.commonwords.save')}</i-button>
                                            </div>
                                        </div>
                                </poptip> : null}
                        </row>}
                    </i-col>
                }
                </row>
            </i-form>
        );
    }
}
