import { Component, Input,Output, AfterContentInit, ReflectiveInjector, ViewChild, ViewContainerRef, ComponentRef, ComponentFactoryResolver, EventEmitter, OnDestroy } from '@angular/core';
import { Subject, Unsubscribable } from 'rxjs';
import { App } from '@global/service/App';

@Component({
    selector: 'app-form-druipart',
    templateUrl: './app-form-druipart.component.html',
    styleUrls: ['./app-form-druipart.component.scss'],
})
export class AppFormDruipart implements AfterContentInit, OnDestroy {

    /**
     * 历史拷贝表单数据
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    public copydata: any;

    /**
     * 当前表单数据
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    public currentdata: any;

    /**
     * 组件要存放的地方
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;

    /**
     * 动态组件实例
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    compRef: ComponentRef<any>;

    constructor(private resolver: ComponentFactoryResolver,private $app:App) {

    }

    /**
     * 表单数据
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    @Input() set data(newVal: any) {
        if (newVal) {
            this.currentdata = newVal;
            if (this.ignorefieldvaluechange) {
                return;
            }
            if (this.copydata) {
                if (Object.is(JSON.stringify(newVal), JSON.stringify(this.copydata))) {
                    return;
                }
                const newFormData: any = JSON.parse(JSON.stringify(newVal));
                const oldDormData: any = JSON.parse(JSON.stringify(this.copydata));
                let refreshRefview = false;
                this.hookItems.some((_hookItem: any) => {
                    if (!Object.is(newFormData[_hookItem], oldDormData[_hookItem])) {
                        refreshRefview = true;
                        return refreshRefview;
                    }
                    return refreshRefview;
                });
                if (refreshRefview) {
                    this.refreshDRUIPart();
                }
            }
            this.copydata = newVal;
        }
    }

    /**
     * 关联视图
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    @Input() public viewname: string;

    /**
     * 刷新关系项
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    @Input() public refreshitems: string = "";

    /**
     * 关系视图类型
     *
     * @type {string}
     * @memberof AppFormDRUIPart
     */
    @Input() public refviewtype: string;

    /**
     * 父数据
     *
     * @type {*}
     * @memberof AppFormDRUIPart
     */
    @Input() public parentdata: any;

    /**
     * 是否忽略表单项值变化
     *
     * @type {boolean}
     * @memberof AppFormDRUIPart
     */
    @Input() public ignorefieldvaluechange: boolean;

    /**
     * 表单状态
     *
     * @type {Subject<any>}
     * @memberof AppFormDRUIPart
     */
    @Input() public formState!: Subject<any>

    /**
     * 触发DEMEDITVIEW9 关系数据保存完成事件
     *
     * @type {EventEmitter}
     * @memberof AppFormDRUIPart
     */    
    @Output() public drdatasaved =new EventEmitter();

    /**
     * 表单状态事件
     *
     * @private
     * @type {(Unsubscribable | undefined)}
     * @memberof AppFormDRUIPart
     */
    private formStateEvent: Unsubscribable | undefined;

    /**
     * 是否刷新关系数据
     *
     * @private
     * @type {boolean}
     * @memberof AppFormDRUIPart
     */
    private isRelationalData: boolean = true;

    /**
     * 刷新节点
     *
     * @private
     * @type {string[]}
     * @memberof AppFormDRUIPart
     */
    private hookItems: string[] = [];

    /**
     * 关系界面向视图下发指令对象
     *
     * @private
     * @type {Subject<any>}
     * @memberof AppFormDRUIPart
     */
    private formDruipart: Subject<any> = new Subject<any>();

    /**
     * 父数据
     *
     * @type {*}
     * @memberof AppFormDRUIPart
     */
    public srfparentdata: any = {};

    ngAfterContentInit(): void {
        this.hookItems = [...this.refreshitems.split(';')];
        if (!this.formState) {
            return;
        }
        this.formStateEvent = this.formState.subscribe(($event: any) => {
            // 表单加载完成
            if (Object.is($event.type, 'load')) {
                this.refreshDRUIPart();
            }
            // 表单保存之前
            if (Object.is($event.type, 'beforesave')) {
                if(Object.is(this.refviewtype,'DEMOBMEDITVIEW9')){
                    Object.assign($event.data,{end:true});
                    this.formDruipart.next({action:'save',data:$event.data});
                }
            }
            // 表单保存完成
            if (Object.is($event.type, 'save')) {
                this.refreshDRUIPart();
            }
            // 表单项更新
            if (Object.is($event.type, 'updateformitem')) {
                if (!$event.data) {
                    return;
                }
                let refreshRefview = false;
                Object.keys($event.data).some((name: string) => {
                    const index = this.hookItems.findIndex((_name: string) => Object.is(_name, name));
                    refreshRefview = index !== -1 ? true : false;
                    return refreshRefview;
                });
                if (refreshRefview) {
                    this.refreshDRUIPart();
                }
            }
        });
        this.refreshDRUIPart();
    }

    /**
     * 刷新关系界面
     *
     * @type {*}
     * @memberof AppFormDRUIPart
     */
    public refreshDRUIPart() {
        if (Object.is(this.parentdata.SRFPARENTTYPE, 'CUSTOM')) {
            this.isRelationalData = false;
        }

        const formData: any = this.currentdata;
        const srfkey = formData.srfkey;

        this.srfparentdata = {};
        Object.assign(this.srfparentdata, this.parentdata);
        Object.assign(this.srfparentdata, { srfparentkey: srfkey });
        if (this.isRelationalData) {
            this.LoadComponent(this);
        }

    }

    /**
     * 加载组件
     * 
     * @param {*} self 
     * @returns 
     * @memberof XtnDialog
     */
    LoadComponent(self: any) {
        let Params = {
            Inputs: { viewdata: JSON.stringify({ srfparentdata: this.srfparentdata }),isembeddedView:true,formDruipart:this.formDruipart },
            Outputs: {
                mditemsload: ($event: any) => {
                    console.log('多数据视图加载完成，触发后续表单项更新');
                },
                drdatasaved: ($event: any) => {
                    this.drdatasaved.emit($event);
                },
                drdatachange: ($event: any) => {
                    console.log('DEMEDITVIEW9 关系数据值变化');
                },
                viewdataschange: ($event: any) => {
                    console.log('视图数据变化');
                },
                viewload: ($event: any) => {
                    console.log('视图加载完成');
                }
            }
        };
        let __Component;
        let fact = self.resolver._factories;
        // 根据名称，摸查出组件名称
        fact.forEach((value: any, key: any) => {
            if (key.name === this.viewname) {
                __Component = key;
            }
        });

        if (!__Component) {
            return;
        }

        // 参数设置
        if (!this.srfparentdata) {
            return;
        }
        let inputProviders = Object.keys(Params).map((inputName) => {
            return { provide: inputName, useValue: Params[inputName] };
        });
        let resolvedInputs = ReflectiveInjector.resolve(inputProviders);
        let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.container.parentInjector);
        if (this.compRef) {
            this.compRef.destroy();
        }
        let factory = this.resolver.resolveComponentFactory(__Component);
        // 创建带参数的组件
        this.compRef = factory.create(injector);
        const { Outputs, Inputs } = Params;
        const __self = this;
        const { inputs, outputs } = factory;
        // 向组件传递参数。
        inputs.forEach((item) => {
            const { propName, templateName } = item;
            const inProps = Inputs[templateName];
            // 给组件上的参数赋值操作。
            if (inProps) {
                __self.compRef.instance[propName] = Inputs[templateName];
            }
        });
        // 向外输入参数，这里主要是判断事件处理。
        outputs.forEach((row) => {
            const { propName, templateName } = row;
            const outProps = __self.compRef.instance[row.propName];
            if (outProps as EventEmitter<any>) {
                // 订阅事件处理
                outProps.subscribe((data) => {
                    if (Outputs[templateName]) {
                        Outputs[templateName](data)
                    }
                });
            }
        });
        // 呈现组件的视图
        this.container.insert(this.compRef.hostView);
    }

    ngOnDestroy(): void {
        if (this.formStateEvent) {
            this.formStateEvent.unsubscribe();
        }
    }



}
