import {Component, ChangeDetectionStrategy, ViewChild, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from 'rxjs';
import {AppService} from '../../services/app.service';
import {CustomerService} from '../../services/customer.service';
import {ICustomer} from '../../model/entities/customer';
import {ICustomerMeeting} from '../../model/entities/customer-meeting';
import {isNull} from 'util';
import {MeetingCalendarComponent} from './meeting-calendar/meeting-calendar.component';
import {TabsComponent} from '../../components/tabs/tabs.component';
import {MeetingListComponent} from './meeting-list/meeting-list.component';
import {MeetingService} from '../../services/meeting.service';
import {IInternalMeeting} from '../../model/entities/internal-meeting';
import {ModalComponent} from '../../components/modal/modal.component';
import {CustomerMeetingDetailComponent} from '../customer-management/customer-view/customer-meeting-detail/customer-meeting-detail.component';
import {Utils} from '../../utils/utils';
import {CustomerMeetingEditComponent} from '../customer-management/customer-view/customer-meeting-edit/customer-meeting-edit.component';
import {InternalMeetingEditComponent} from './internal-meeting-edit/internal-meeting-edit.component';
import {Factory} from '../../factory/factory';
import {InternalMeetingDetailComponent} from './internal-meeting-detail/internal-meeting-detail.component';
import {IMeetingData} from '../../model/virtual/meeting-data';
import {IOperatorMeeting} from '../../model/entities/operator-meeting';
import {OperatorService} from '../../services/operator.service';
import {IOperator} from '../../model/entities/operator';
import {OperatorMeetingDetailComponent} from '../operators/operator-view/operator-meeting-detail/operator-meeting-detail.component';
import {ProductionService} from '../../services/production.service';
import {ServiceService} from '../../services/service.service';
import {IProduction} from '../../model/entities/production';
import {IService} from '../../model/entities/service';
import {IProductionMeeting} from '../../model/entities/production-meeting';
import {IServiceMeeting} from '../../model/entities/service-meeting';
import {
    ProductionMeetingDetailComponent
} from '../productions/production-view/production-meeting-detail/production-meeting-detail.component';
import {
    ServiceMeetingDetailComponent
} from '../services/service-view/service-meeting-detail/service-meeting-detail.component';

@Component({
    selector: 'app-start',
    changeDetection: ChangeDetectionStrategy.OnPush,
    templateUrl: './start.component.html',
    styleUrls: ['./start.component.scss']
})

export class StartComponent implements OnInit, OnDestroy {

    @ViewChild('tabsStart', {static: true}) tabsStart: TabsComponent;
    @ViewChild('meetingCalendar', {static: true}) meetingCalendar: MeetingCalendarComponent;
    @ViewChild('meetingList', {static: true}) meetingList: MeetingListComponent;
    @ViewChild('modalInternalMeetingEdit', {static: true}) modalInternalMeetingEdit: ModalComponent;
    @ViewChild('modalInternalMeetingDetailStart', {static: true}) modalInternalMeetingDetailStart: ModalComponent;
    @ViewChild('internalMeetingEdit', {static: true}) internalMeetingEdit: InternalMeetingEditComponent;
    @ViewChild('internalMeetingDetailStart', {static: true}) internalMeetingDetailStart: InternalMeetingDetailComponent;
    @ViewChild('modalCustomerMeetingDetailStart', {static: true}) modalCustomerMeetingDetailStart: ModalComponent;
    @ViewChild('modalCustomerMeetingEditStart', {static: true}) modalCustomerMeetingEditStart: ModalComponent;
    @ViewChild('customerMeetingDetailStart', {static: true}) customerMeetingDetailStart: CustomerMeetingDetailComponent;
    @ViewChild('customerMeetingEditStart', {static: true}) customerMeetingEditStart: CustomerMeetingEditComponent;
    @ViewChild('modalOperatorMeetingDetailStart', {static: true}) modalOperatorMeetingDetailStart: ModalComponent;
    @ViewChild('operatorMeetingDetailStart', {static: true}) operatorMeetingDetailStart: OperatorMeetingDetailComponent;
    @ViewChild('modalProductionMeetingDetailStart', {static: true}) modalProductionMeetingDetailStart: ModalComponent;
    @ViewChild('productionMeetingDetailStart', {static: true}) productionMeetingDetailStart: ProductionMeetingDetailComponent;
    @ViewChild('modalServiceMeetingDetailStart', {static: true}) modalServiceMeetingDetailStart: ModalComponent;
    @ViewChild('serviceMeetingDetailStart', {static: true}) serviceMeetingDetailStart: ServiceMeetingDetailComponent;

    private customers: ICustomer[];
    private customersById: {};
    private operators: IOperator[];
    private operatorsById: {};
    private productions: IProduction[];
    private productionsById: {};
    private services: IService[];
    private servicesById: {};
    private customersSub: Subscription;
    private operatorsSub: Subscription;
    private productionsSub: Subscription;
    private servicesSub: Subscription;
    private meetingData: IMeetingData;
    private meetingsSub: Subscription;
    private customerMeetings: ICustomerMeeting[];
    private internalMeetings: IInternalMeeting[];
    private operatorMeetings: IOperatorMeeting[];
    private productionMeetings: IProductionMeeting[];
    private serviceMeetings: IServiceMeeting[];

    constructor(
        private appService: AppService,
        private customerService: CustomerService,
        private operatorService: OperatorService,
        private productionService: ProductionService,
        private serviceService: ServiceService,
        private meetingService: MeetingService) {

    }

    ngOnInit() {
        this.customers = null;
        this.customersById = {};
        this.operators = null;
        this.operatorsById = {};
        this.customerMeetings = null;
        this.internalMeetings = null;
        this.operatorMeetings = null;
        this.productionMeetings = null;
        this.serviceMeetings = null;

        this.customerService.apiGetCustomerData();
        this.meetingService.apiGetMeetingData();
        this.operatorService.apiGetOperatorData();
        this.productionService.apiGetProductionData();
        this.serviceService.apiGetServiceData();

        this.customersSub = this.customerService.getCustomers$().subscribe(
            data => {
                this.customers = data;
                this.customersById = Utils.getSortedObjFromArray(this.customers, 'id');
                this.setComponentData();
            }
        );
        this.operatorsSub = this.operatorService.getOperators$().subscribe(
            data => {
                this.operators = data;
                this.operatorsById = Utils.getSortedObjFromArray(this.operators, 'id');
                this.setComponentData();
            }
        );
        this.productionsSub = this.productionService.getProductions$().subscribe(
            data => {
                this.productions = data;
                this.productionsById = Utils.getSortedObjFromArray(this.productions, 'id');
                this.setComponentData();
            }
        );
        this.servicesSub = this.serviceService.getServices$().subscribe(
            data => {
                this.services = data;
                this.servicesById = Utils.getSortedObjFromArray(this.services, 'id');
                this.setComponentData();
            }
        );

        this.meetingsSub = this.meetingService.getMeetingsData$().subscribe(
            data => {
                this.meetingData = data;
                if (!isNull(data)) {
                    this.customerMeetings = data.customerMeetings;
                    this.internalMeetings = data.internalMeetings;
                    this.operatorMeetings = data.operatorMeetings;
                    this.productionMeetings = data.productionMeetings;
                    this.serviceMeetings = data.serviceMeetings;
                } else {
                    this.customerMeetings = null;
                    this.internalMeetings = null;
                    this.operatorMeetings = null;
                    this.productionMeetings = null;
                    this.serviceMeetings = null;
                }
                this.setComponentData();
            }
        );
    }

    /**
     * Sets component data
     */
    private setComponentData() {
        if (!isNull(this.customers) &&
            !isNull(this.operators) &&
            !isNull(this.productions) &&
            !isNull(this.services) &&
            !isNull(this.customerMeetings) &&
            !isNull(this.internalMeetings) &&
            !isNull(this.operatorMeetings) &&
            !isNull(this.productionMeetings) &&
            !isNull(this.serviceMeetings)
        ) {
            this.meetingCalendar.setData(
                this.customersById,
                this.operatorsById,
                this.productionsById,
                this.servicesById,
                this.customerMeetings,
                this.internalMeetings,
                this.operatorMeetings,
                this.productionMeetings,
                this.serviceMeetings
            );
            this.meetingList.setData(
                this.customersById,
                this.operatorsById,
                this.productionsById,
                this.servicesById,
                this.customerMeetings,
                this.internalMeetings,
                this.operatorMeetings,
                this.productionMeetings,
                this.serviceMeetings
            );
        }
    }

    public rowClickedCustomerMeeting(e: ICustomerMeeting): void {
        this.modalCustomerMeetingDetailStart.openModal();
        this.customerMeetingDetailStart.setData(this.customersById[e.customer_id], e);
    }

    public rowClickedOperatorMeeting(e: IOperatorMeeting): void {
        this.modalOperatorMeetingDetailStart.openModal();
        this.operatorMeetingDetailStart.setData(this.operatorsById[e.operator_id], e);
    }

    public rowClickedInternalMeeting(e: IInternalMeeting): void {
        this.modalInternalMeetingDetailStart.openModal();
        this.internalMeetingDetailStart.setData(e);
    }

    public rowClickedProductionMeeting(e: IProductionMeeting): void {
        this.modalProductionMeetingDetailStart.openModal();
        this.productionMeetingDetailStart.setData(this.productionsById[e.production_id], e);
    }

    public rowClickedServiceMeeting(e: IServiceMeeting): void {
        this.modalServiceMeetingDetailStart.openModal();
        this.serviceMeetingDetailStart.setData(this.servicesById[e.service_id], e);
    }

    public editCustomerMeetingFunction(customerMeeting: ICustomerMeeting): void {
        this.meetingService.apiEditCustomerMeeting(customerMeeting).subscribe(
            data => {
                this.customerMeetingDetailStart.updateData(data.result_data as ICustomer);
            },
            error => {
            }
        );
    }

    public editCustomerMeetingReportFunction(reportValues: any): void {
        const meetingId: number = reportValues.id;
        const report: string = reportValues.report;
        this.meetingService.apiEditCustomerMeetingReport(meetingId, report).subscribe(
            data => {
                this.customerMeetingDetailStart.updateData(data.result_data as ICustomer);
            },
            error => {}
        );
    }

    public deleteCustomerMeetingFunction(customerMeetingId: number): void {
        this.meetingService.apiDeleteCustomerMeeting(customerMeetingId).subscribe(
            data => {
                this.modalCustomerMeetingDetailStart.exitModal();
            },
            error => {
            }
        );
    }

    public editOperatorMeetingFunction(operatorMeeting: IOperatorMeeting): void {
        this.meetingService.apiEditOperatorMeeting(operatorMeeting).subscribe(
            data => {
                this.operatorMeetingDetailStart.updateData(data.result_data as IOperator);
            },
            error => {
            }
        );
    }

    public editOperatorMeetingReportFunction(reportValues: any): void {
        const meetingId: number = reportValues.id;
        const report: string = reportValues.report;
        this.meetingService.apiEditOperatorMeetingReport(meetingId, report).subscribe(
            data => {
                this.operatorMeetingDetailStart.updateData(data.result_data as IOperator);
            },
            error => {}
        );
    }

    public deleteOperatorMeetingFunction(operatorMeetingId: number): void {
        this.meetingService.apiDeleteOperatorMeeting(operatorMeetingId).subscribe(
            data => {
                this.modalOperatorMeetingDetailStart.exitModal();
            },
            error => {
            }
        );
    }

    public editInternalMeetingFunction(internalMeeting: IInternalMeeting): void {
        this.meetingService.apiEditInternalMeeting(internalMeeting).subscribe(
            data => {
                this.internalMeetingDetailStart.updateData(data.result_data as IInternalMeeting);
            },
            error => {
            }
        );
    }

    public deleteInternalMeetingFunction(internalMeetingId: number): void {
        this.meetingService.apiDeleteInternalMeeting(internalMeetingId).subscribe(
            data => {
                this.modalInternalMeetingDetailStart.closeModal();
            },
            error => {
            }
        );
    }

    public editInternalMeetingReportFunction(reportValues: any): void {
        const meetingId: number = reportValues.id;
        const report: string = reportValues.report;
        this.meetingService.apiEditInternalMeetingReport(meetingId, report).subscribe(
            data => {
                this.internalMeetingDetailStart.setData(data.result_data as IInternalMeeting);
            },
            error => {}
        );
    }

    public openCreateMeeting(): void {
        this.modalInternalMeetingEdit.openModal();
        this.internalMeetingEdit.setData(Factory.getEmptyInternalMeeting(), true);
    }

    public createMeetingInternal(internalMeeting: IInternalMeeting): void {
        this.meetingService.apiCreateInternalMeeting(internalMeeting).subscribe(
            data => {
                this.modalInternalMeetingEdit.closeModal();
            },
            error => {}
        );
    }

    public editProductionMeetingFunction(productionMeeting: IProductionMeeting): void {
        this.meetingService.apiEditProductionMeeting(productionMeeting).subscribe(
            data => {
                this.productionMeetingDetailStart.updateData(data.result_data as IProduction);
            },
            error => {
            }
        );
    }

    public editProductionMeetingReportFunction(reportValues: any): void {
        const meetingId: number = reportValues.id;
        const report: string = reportValues.report;
        this.meetingService.apiEditProductionMeetingReport(meetingId, report).subscribe(
            data => {
                this.productionMeetingDetailStart.updateData(data.result_data as IProduction);
            },
            error => {}
        );
    }

    public deleteProductionMeetingFunction(productionMeetingId: number): void {
        this.meetingService.apiDeleteProductionMeeting(productionMeetingId).subscribe(
            data => {
                this.modalProductionMeetingDetailStart.exitModal();
            },
            error => {
            }
        );
    }

    public editServiceMeetingFunction(serviceMeeting: IServiceMeeting): void {
        this.meetingService.apiEditServiceMeeting(serviceMeeting).subscribe(
            data => {
                this.serviceMeetingDetailStart.updateData(data.result_data as IService);
            },
            error => {
            }
        );
    }

    public editServiceMeetingReportFunction(reportValues: any): void {
        const meetingId: number = reportValues.id;
        const report: string = reportValues.report;
        this.meetingService.apiEditServiceMeetingReport(meetingId, report).subscribe(
            data => {
                this.serviceMeetingDetailStart.updateData(data.result_data as IService);
            },
            error => {}
        );
    }

    public deleteServiceMeetingFunction(serviceMeetingId: number): void {
        this.meetingService.apiDeleteServiceMeeting(serviceMeetingId).subscribe(
            data => {
                this.modalServiceMeetingDetailStart.exitModal();
            },
            error => {
            }
        );
    }

    /**
     * Destroy
     */
    ngOnDestroy(): void {
        if (this.customersSub !== null && this.customersSub !== undefined) {
            this.customersSub.unsubscribe();
        }
        if (this.meetingsSub !== null && this.meetingsSub !== undefined) {
            this.meetingsSub.unsubscribe();
        }
    }
}
