
// Core imports
import { Component, OnInit, Input, Output, EventEmitter, Inject, PLATFORM_ID } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'
import { trigger,state, style, transition, animate } from '@angular/animations'
import { NgForm }              from '@angular/forms'

// Services
import { SendCartConfiguration } from '../../services/cnf.send-cart'
import { SendCartService } from '../../services/svc.send-cart'
import { map } from 'rxjs/operators'


/**
 * @name AddressBlockComponent
 * @description *watdo?*
 * @author Kasper Hansen - Klean
 * @since *wendis?*
 * @extends
 */
@Component({
    moduleId: module.id+ '',
    selector: 'send-cart-address-block',
    templateUrl: './template/t--addressBlock.pug',
    styleUrls: ['sty.addressBlock.scss'],
    animations: [
        trigger('In', [

            state('unload', style({ opacity: 1, transform: "translateX(0)"})),
            state('load', style({ opacity: 0, transform: "translateX(-20px)"})),

            transition('load => unload', [
                animate('100ms ease-in', style({ transform: "translateX(10px)"})),
                animate('75ms ease-in')
            ]),

            transition('unload => load', [
                animate('75ms ease-in', style({ transform: "translateX(10px)" })),
                animate('100ms ease-in')
            ])
        ])
    ]
})

export class AddressBlockComponent implements OnInit {

    // ---- Variables ---- \\
    private inputs
    values: any = {}
    element: any = {}


    inputValidity: any[] = []
    rules = new Map
    companyRule: any = 0

    b2bCustomer: boolean | any = undefined
    b2bCustomerRule: false | string = 'blank'

    _session: any


    @Input() model: string
    @Output() result: EventEmitter<any> = new EventEmitter()



    constructor(
        @Inject(PLATFORM_ID) private _platformId,
        private _sendCart: SendCartService,
        private _configuration: SendCartConfiguration
    ) {}

    



    // ---- Lifecycle hooks ---- \\
    ngOnInit() {

        this.inputs =  this._configuration.returnInputs()

        

        // Set values from session if model exists in session
        if(isPlatformBrowser(this._platformId)) {
            this._session = this._sendCart.sessionStore('get')

            if(!!this._session[this.model]) {

                for(let key of Object.keys(this._session[this.model])) {
                    this.element[this.model + '_' + key] = this._session[this.model][key]
                    this.values[key] = this._session[this.model][key]

                    // This is a is not great, it should be handled through observable logic, but a bunch of this code needs to be reworked to work with observables, to fix timing issues
                    setTimeout(() => {

                        if(key == 'company-rule') {
                            this.companyRule = this._session[this.model][key] ? 1 : 0
                            this.toggleRule('company', this.companyRule)
                        }

                    }, 1000)
                }
            }
        

            // Sets default on load
            for(let input of this.inputs) {

                
                
                input.id = this.model+'_'+input.label.replace(' ', '')
                this.checkValid(input.id, this.values[input.label.replace(' ', '')], input.pattern, false)
                

                if(!this.element[input.id])
                    this.element[input.id] = ''

                if(!!input.default) {

                    let identifier = input.label.replace(' ', '')

                    this.values[identifier] = input.default
                    this.element[input.id] = input.default
                }
            }

            this.values['company-rule'] = Boolean(parseInt(this.companyRule))

            this.result.emit(this.values)
        }

        // Gets customers information, and displays it if applicable
        this._sendCart.getCustomers()
            .pipe(
                // map(() => {
                //     return {"status":"success","data":{"list":[{"value":"1265","label":"Mikkel Bundgaard, Teststreet 08, 8000 Aarhus C"},{"value":"1283","label":"Per Nielsen, Test street, 8000 Aarhus C"},{"value":"1285","label":"Mix Bundgaard, Test street, 8000 Aarhus C"},{"value":"1286","label":"Kasper Hansen, Catstreet 666, 8000 Aarhus C"}]},"serverHash":"devjyskkleandk_23045864"}
                // }),
                map((result: any) => {
                    return result.data ? result.data : false
                })
            )
            .subscribe((result) => {

                this.b2bCustomer = result

                console.log(result, ('list' in result) && !result.list)

                // if list exists, but is false, set the value in the this.values
                if(('list' in result) && !result.list) {
                    
                    this.updateElement(false, 'b2bcustomer')

                } else if(this._sendCart.sessionStore('get') && this._sendCart.sessionStore('get')['billing'] && this._sendCart.sessionStore('get')['billing']['b2bcustomer']) {

                    // If rule exists, then set the value
                    this.b2bCustomerRule = this._sendCart.sessionStore('get')['billing']['b2bcustomer']
                } else {
                    this.updateElement('blank', 'b2bcustomer')
                }
            })

    }



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

    toggleRule(rule, value?) {

        // create an input for updateElement, if a rule is changed, so the backend receives the data
        let val = !!value.srcElement ? value.srcElement.value : value
        this.updateElement({srcElement: {value: Boolean(parseInt(val))}}, rule+'-rule')


        if(val !== 'undefined') {

            this.rules.set(rule, Boolean(parseInt(val)))
        } else {

            this.rules.set(rule, !this.rules.get(rule))
        }
    }


    /**
     *  Replaces spaces in identifier with nothing, then sets the sources value into the values array
     * then saves the value into the sessionStore and exposes it through the EventEmitter
     * 
     * @param event
     * @param identifier 
     */
    updateElement(event: string | any, identifier: string) {

        identifier = identifier.replace(' ', '')

        // If event is a full-blown source reference, get value, else parse value as it comes in
        this.values[identifier] = event.srcElement ? event.srcElement.value : event

        // Save and expose
        this._sendCart.sessionStore('set', this.model, this.values)
        this.result.emit(this.values)
    }


    /**
     * Checks if field is valid, only triggers the flag, if fromEvent is true
     * 
     * @param identifier 
     * @param field 
     * @param regex 
     * @param fromEvent 
     */
    checkValid(identifier, field, regex, fromEvent = true) {
        
        let flagEmpty = true

        // Everything else that is logical - What does this even mean? :|
        if(fromEvent) {

            field = field.srcElement.value
        } else {
            flagEmpty = false
        }
        

        if(!!field && field.match(regex) == null) {

            if(flagEmpty)
                this.inputValidity[identifier] = true
        }
        else {
            this.inputValidity[identifier] = false
        }
    }

    

    /**
     * Will trim whitespace from the value of an input
     * 
     * @param event 
     * @param id - id of input, used for reference in `this.element`
     * @param label
     * 
     * @requires updateElement()
     */
    removeWhitespace(event, id: string, label: string) {
        let trimmedValue = event.target.value.trim()

        this.element[id] = trimmedValue
        event.target.value = trimmedValue

        // set localstorage version of trimmed values
        this.updateElement(event, label)
    }

}