
import { Component, OnInit, OnDestroy, HostListener, Input } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'

// Interfaces
import { ISubscription } from 'rxjs/Subscription'

interface IHeaderHeights {
    default: number;
    desktop?: number;
    tablet?: number;
    device?: number;
}

// Global / Shared Services
import { HelperService } from '@k-services/svc.helper'
import { BasketService } from '@k-services/svc.basket'

// Module Services
import { ConfiguratorService }  from '../../services/svc.configurator'
import { ConfiguratorProductLoaderService } from '../../services/svc.configurator-product-reloader'
import { DiscountsService } from '@k-core/common/discount/services/svc.discounts'


@Component({
    moduleId: module.id+ '',
    selector: 'configurator-price',
    templateUrl: './tpl.price.pug',
    styleUrls: ['sty.price.scss']
})

export class PriceComponent {

    // ---- Variables ---- \\
    // Data
    @Input('specs') specs: any
    price: any
    discount_price: number
    defaults: any[] = [
        {
            'id': 'type_id'
        },
        {
            'id': 'measurements'
        },
        {
            'id': 'dessin'
        },
        {
            'id': 'details'
        }
    ]

    dontValidate: string[] = ['marking']
    product: any
    resultMap: any = new Map
    result: any[] = []
    quantity: number = 1
    localDiscounts: any[] = []
    discounts: any[] = []
    discountMessage: string = 'subtracted at checkout'

    // Layout
    basketWidth: number
    headerHeight: number        = 58
    headerHeights: IHeaderHeights = {
        default: 58
    }

    // States
    isAccepted: boolean = true
    fixed: boolean = false
    isPalm: boolean
    isLap: boolean
    buttonClicked: boolean = false
    isModifiable: boolean = false

    // Observable subscriptions
    private specSubscription: ISubscription
    private productSubscription: ISubscription
    private validSubscription: ISubscription
    private validationResultsSubscription: ISubscription
    private priceSubscription: ISubscription
    

    constructor(
        public helper: HelperService,
        public service: ConfiguratorService,
        private _preset: ConfiguratorProductLoaderService,
        private _basket: BasketService,
        private _discount: DiscountsService
    ) {

        this._preset.preset$.subscribe((preset) => {
            // this.quantity =(!!preset.details.quantity ?  parseInt(preset.details.quantity) : this.quantity)

            this.isModifiable = this._preset.isModify
        })

        this.specSubscription = service.spec$.subscribe((response) => {

            // New
            service.validate(this.defaults, this.dontValidate)
        })


        this.productSubscription = service.product$.subscribe((response) => {
            
            this.product = response

            // New
            service.validate(this.defaults, this.dontValidate)
        })


        // Subscribe to valid
        this.validSubscription = service.valid$.subscribe((response) => {
            this.isAccepted = response
        })

        // Subscribe to validation results
        this.validationResultsSubscription = service.validationResults$.subscribe((response) => {
            this.resultMap = response

            //&: This should probably be refactored so that results in template are shown based on resultMap
            this.result = Array.from(response)
        })




        this.priceSubscription = service.price$.subscribe((response) => {
            this.price = response

            this._getDiscount()
        })

        // Set breakpoint state
        this.isPalm = this.helper.currentBreakPoint('palm')
        this.isLap = this.helper.currentBreakPoint('lap')


        this._basket.getDiscounts().then((response) => {
            this.discounts = response.data.rules

            if(!!this._basket && this._basket.basket) {

                this.localDiscounts = this._basket.basket.filter((product) => product.id.includes('-cu--') || product.id.includes('-ir--')).filter((discount) => !!discount.data.ruleData && discount.data.ruleData.action != 'by_fixed_of_base')
            }
        })

    }





    // ---- Lifecycle hooks ---- \\
    ngOninit() {
        // Set the width of basket on init
        this.setWidth()
    }

    ngOnDestroy() {
        this.specSubscription.unsubscribe()
        this.productSubscription.unsubscribe()
        this.validSubscription.unsubscribe()
        this.validationResultsSubscription.unsubscribe()
        this.priceSubscription.unsubscribe()

        this._preset.isModify = false
    }




    // ---- Functions ---- \\

    /**
     * Submits the product, checks the state, and removes the existing one from the basket
     * the creates and identifier through the `helper.bin2hex()` command with a stringified
     * id of based off the product
     * 
     * displays Modal when completed
     * 
     * @param {boolean} state 
     */
    submitProduct(state: boolean) {
        if(state) {
            if(!!this._preset.storedId && this.isModifiable) {
                this._basket.removeProductFromBasket(this._preset.storedId)
            }
            
            if((!!this.product && !!this.product.marking) && (this.product.marking == undefined || this.product.marking == 'undefined')) {
                delete this.product.marking
            }

            this.product.sku = this.service.configuratorType

            let identifier = `-conf--${this.helper.bin2hex(JSON.stringify(this.product))}`
            this._basket.addProduct(identifier, this.quantity, this.product)
                .subscribe((response) => {
                    if(response == 'success') {

                        // Set unique key if none exists
                        this._basket.setKey()

                        // Show modal
                        this.service.setModal(true)
                    }
                })



        }
    }


    /**
     * Will set the width of basket to that of the container
     */
    setWidth() {
        if(isPlatformBrowser && typeof window !== 'undefined') {
            this.basketWidth = document.querySelector('.js-basket').getBoundingClientRect().width
        }
    }


    /**
     * Finds the container position from top, and when position
     * is equal to or below `0 + offset` basket is set to fixed
     */
    setFixedState() {
        if(isPlatformBrowser && typeof window !== 'undefined') {
            let offset = 22

            // When palm, make a bigger offset
            if(this.isPalm || this.isLap) {
                offset = this.headerHeight + 22
            }
            

            if(document.querySelector('.js-basket')) {
                let basket_container = document.querySelector('.js-basket').getBoundingClientRect(),
                    pos = basket_container.top
    
                // Fixed check
                if(pos <= 0 + offset) {
                    this.fixed = true
                }
                else {
                    this.fixed = false
                }
            }
        }
    }

    setQuantity(event) {
        this.quantity = event
    }

    // Set Type (Type, Mål, color, Detailer)
    // Used in Suntex 
    setSelector(selector_id) {
        this.service.setSpecSelector(selector_id)
    }

    /**
     * Clear product configurator product and reload configurtor 
     */
    clear() {

        this.service.setReset(true)
        this._preset.clearSelection()
        this._preset.clearPreviousBuild()

    }



    _getDiscount() {

        if(!!this.product && this.discounts && this.price) {

            this.product.price = this.price.data.price
            this.product.quantity = this.quantity


            let discountProduct = {
                sku: this.service.configuratorType,
                id: '-conf--prebuild',
                type_id: this.product.type_id,
                options: []
            }

            for(const [key, value] of Object.entries(this.product)) {
                discountProduct.options.push({ code: key, value: value })
            }
            

            this._discount.request([...this.localDiscounts, discountProduct]).then((response) => {

                if(response == 0) {
                    this.discount_price = null
                } else {
                    this.discount_price = response

                    this._findActiveDiscount()
                }
            })
        }
    }


    _findActiveDiscount() {

        for(let discount of this.discounts) {

            for(let condition of discount.conditions) {

                switch(condition.attribute) {

                    case 'curtain_type':

                        if(condition.value.includes(this.product.type_id.toLowerCase())) {

                            this.discountMessage = discount.name
                        }

                        break
                    
                    default:

                        this.discountMessage = discount.name

                        break
                }
            }

        }

    }
    // ---- Listeners ---- \\


    /**
	 * Listen to window scroll
	 */
	@HostListener('document:scroll', ['$event'])
	onWindowScroll() {
        this.setFixedState()
        
        if(!this.basketWidth)
            this.setWidth()
    }
    
    /**
	 * Listen to window resize
	 */
	@HostListener('window:resize', ['$event'])
	onWindowResize() {
        this.setWidth()
        
        // Set breakpoint state
        this.isPalm = this.helper.currentBreakPoint('palm')
        this.isLap = this.helper.currentBreakPoint('lap')
	}
}