import { Component, ChangeDetectionStrategy, ElementRef } from "@angular/core"
import { DocDbPopupActionI, DocDbPopupTypeE } from "@peek/peek_core_docdb"
import {
    PopupTriggeredParams,
    PrivateDocDbPopupService
} from "@peek/peek_core_docdb/_private/services/PrivateDocDbPopupService"
import {
    DocDbPopupClosedReasonE,
    DocDbPopupDetailI
} from "@peek/peek_core_docdb"
import { BehaviorSubject } from "rxjs"
import { DOCDB_POPUP } from "@peek/peek_core_docdb/constants"

type Popup = "tooltip" | "summary" | "detail"

// This is a root/global component
@Component({
    selector: "popup-component",
    templateUrl: "popup.component.html",
    styleUrls: ["popup.component.scss"],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class PopupComponent {
    DOCDB_POPUP = DOCDB_POPUP
    
    params$ = new BehaviorSubject<PopupTriggeredParams>(null)
    modalAction$ = new BehaviorSubject<DocDbPopupActionI>(null)
    currentPopup$ = new BehaviorSubject<Popup>(null)
    
    left$ = new BehaviorSubject<number>(0)
    right$ = new BehaviorSubject<number>(0)
    top$ = new BehaviorSubject<number>(0)
    bottom$ = new BehaviorSubject<number>(0)
    
    constructor(
        private popupService: PrivateDocDbPopupService,
        private element: ElementRef
    ) {
        this.popupService.showTooltipPopupSubject.subscribe(val => {
            this.openPopup(val)
            this.currentPopup = "tooltip"
            document.body.appendChild(this.element.nativeElement)
        })
        this.popupService.showSummaryPopupSubject.subscribe(val => {
            this.openPopup(val)
            this.currentPopup = "summary"
            document.body.appendChild(this.element.nativeElement)
        })
        this.popupService.showDetailPopupSubject.subscribe(val => {
            this.openPopup(val)
            this.currentPopup = "detail"
            document.body.appendChild(this.element.nativeElement)
        })
        
        this.popupService.hideTooltipPopupSubject.subscribe(() => this.closePopup())
        this.popupService.hideSummaryPopupSubject.subscribe(() => this.closePopup())
        this.popupService.hideDetailPopupSubject.subscribe(() => this.closePopup())
    }
    
    get params() {
        return this.params$.getValue()
    }
    
    set params(value) {
        this.params$.next(value)
    }
    
    get modalAction() {
        return this.modalAction$.getValue()
    }
    
    set modalAction(value) {
        this.modalAction$.next(value)
    }
    
    get currentPopup() {
        return this.currentPopup$.getValue()
    }
    
    set currentPopup(value) {
        this.currentPopup$.next(value)
    }
    
    get left() {
        return this.left$.getValue()
    }
    
    set left(value) {
        this.left$.next(value)
    }
    
    get right() {
        return this.right$.getValue()
    }
    
    set right(value) {
        this.right$.next(value)
    }
    
    get top() {
        return this.top$.getValue()
    }
    
    set top(value) {
        this.top$.next(value)
    }
    
    get bottom() {
        return this.bottom$.getValue()
    }
    
    set bottom(value) {
        this.bottom$.next(value)
    }
    
    closePopup(): void {
        if (!this.params) {
            return
        }
        
        this.params = null
        this.popupService.hidePopupWithReason(
            DocDbPopupTypeE.summaryPopup,
            DocDbPopupClosedReasonE.closedByApiCall
        )
    }
    
    showDetailsPopup(): void {
        const params = this.params
        
        this.popupService.hidePopupWithReason(
            DocDbPopupTypeE.summaryPopup,
            DocDbPopupClosedReasonE.userDismissedPopup
        )
        
        this.popupService.showPopup(
            true,
            DocDbPopupTypeE.detailPopup,
            params.triggeredByPlugin,
            this.makeMouseEvent(params),
            params.modelSetKey,
            params.objectKey,
            params.options
        )
    }
    
    headerDetails(details: DocDbPopupDetailI[]): string {
        return details
            .filter(d => d.showInHeader)
            .map(d => d.value)
            .join(", ")
    }
    
    bodyDetails(details: DocDbPopupDetailI[]): DocDbPopupDetailI[] {
        return details.filter(d => !d.showInHeader)
    }
    
    modalActionClicked(item: DocDbPopupActionI): void {
        this.actionClicked(item)
        this.closeModal()
    }
    
    actionClicked(item: DocDbPopupActionI): void {
        if (item.children?.length) {
            this.modalAction = item
        }
        else {
            item.callback()
        }
        this.closePopup()
    }
    
    modalName(): string {
        if (this.modalAction == null) {
            return null
        }
        
        return this.modalAction.name || this.modalAction.tooltip
    }
    
    closeModal(): void {
        this.modalAction = null
    }
    
    modalChildActions(): DocDbPopupActionI[] {
        return this.modalAction == null ? [] : this.modalAction.children
    }
    
    openPopup(params: any) {
        this.params = params
        
        if (params.position.changedTouches) {
            this.setHorizontal(params.position.changedTouches[0].clientX)
            this.setVertical(params.position.changedTouches[0].clientY)
        }
        else {
            this.setHorizontal(params.position.x)
            this.setVertical(params.position.y)
        }
    }
    
    setHorizontal(x: number): void {
        const width = window.innerWidth
        
        if (x > width / 2) {
            this.right = Math.round(width - x)
            this.left = null
        }
        else {
            this.left = Math.round(x)
            this.right = null
        }
    }
    
    setVertical(y: number): void {
        const height = window.innerHeight
        
        if (y > height / 2) {
            this.bottom = Math.round(height - y)
            this.top = null
        }
        else {
            this.top = Math.round(y)
            this.bottom = null
        }
    }
    
    private makeMouseEvent(params) {
        let x = 0
        let y = 0
        
        if (params.position.changedTouches) {
            x = params.position.changedTouches[0].clientX
            y = params.position.changedTouches[0].clientY
        }
        else {
            x = params.position.x
            y = params.position.y
        }
        
        return <any>{
            preventDefault: () => false,
            x,
            y
        }
    }
}
