/**
 * Made by mkcomponent.sh
 * * Change to Fileheader info *
*/

// Core Imports
import { Component, Inject, PLATFORM_ID, SimpleChange } from '@angular/core'
import { ActivatedRoute, Params, Router, NavigationEnd }   from '@angular/router'
import 'rxjs/add/operator/switchMap'

// Types
import { CategoryType }             from '@k-types/category'

// Services
import { CategoryService }          from '@k-services/svc.category'
import { SeoService }               from '@k-services/svc.seo'
import { HelperService }            from '@k-services/svc.helper'

import { store } from '@k-settings/app-setup'
import { Observable, BehaviorSubject, Subject } from 'rxjs'
import { tap, map } from 'rxjs/operators'
import { isPlatformBrowser } from '@angular/common'

/**
 * @todo Make error more correct, as observable instead of static, footwork is done
 */
@Component({
    moduleId: module.id+ '',
    selector: 'category-view',
    templateUrl: './template/t--view.pug',
    styleUrls: ['sty.view.scss']
})

export class ViewComponent {

    // ---- Variables ---- \\

    // Display Category
    category: CategoryType
    showError:boolean = false

    // Containers
    products: any

    // Scoping
    storeType: string = store
    listType: string = 'block'
    displayBackButton: boolean = false
    
    // Quantity
    checkQuantity: boolean = false
    productQuantityStateMap: Map<string, boolean> = new Map

    // Pagination
    pageIndex:number = 0
    pageSize:number = 25
    lowValue:number = 0
    highValue:number = this.pageSize // Uses pageSize as max value for when the page should shift and how the object should be spliced

    // Observables
    // - Stuff needs to be here to be cool
    loadingSource = new BehaviorSubject<boolean>(true)
    loading$ = this.loadingSource.asObservable()

    errorSource = new BehaviorSubject<boolean>(true)
    error$ = this.errorSource.asObservable()

    productsSource = new Subject()
    products$ = this.productsSource.asObservable()

    isLarge: boolean = false


    constructor(
        @Inject(PLATFORM_ID) private _platformId,
        private categoryService: CategoryService,
        private route: ActivatedRoute,
        private _seo: SeoService,
        private _helper: HelperService,
        private _router: Router // used in constructor
    ) {
        // Scroll to top - This should really be supplied in a helper of sorts
        _router.events.subscribe(e => {
            if (e instanceof NavigationEnd) {
                this._helper.scrollTo();
            }
        });

        
        if(isPlatformBrowser(this._platformId)) {
            this.isLarge = window.innerWidth > 1440
        }

        // If using route params, ! Generally this system works on using `**` for fluent stacked categories
        this.route.params
        .pipe(
            tap((params: Params) => {

                if(this._router.url.split('/').reverse()[0] != params['categorykey']) {
                    params['categorykey'] = this._router.url.split('/').reverse()[0]
                }

                if(!params['categorykey']) {
                    this.errorSource.next(false)
                    throw new Error('no categorykey set')
                } else {
                    this.errorSource.next(true) // Remove error once fulfilled
                }
            })
        )
        .subscribe({
            next: (params: Params) => {
                this.getCategory(params['categorykey'])
            },
            error: e => console.error(e)
        })

        // If using ** as a source
        this.route.url.subscribe((data) => {
            
            // Reverse order to show the last one first
            data = data.reverse()

            // If any URL segments are found, get the category based on the first path in array
            if(data.length) {
                this.getCategory(data[0].path)
            }
        })

    }


    // --- Lifecycle Hooks ---- \\

    ngOnInit(): void {

    }

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

    // PUBLIC

    /**
     * Get category data for the given category and assign data to `category` variable
     * 
     * @param category 
     */
    getCategory(category) {
        this.categoryService.getCollectionByUrlKey(category)
            .pipe(
                tap((response) => {

                    console.log('run getCollectionByUrlKey', response, category)

                    // Cause error if there is no products
                    if(response.products.length < 1) {

                        this.errorSource.next(false)
                        throw new Error('less than 1 product available')
                    } else {
                        this.errorSource.next(true) // Remove error once fulfilled
                    }
                        
                }),
                tap((response) => {

                    // Set SEO
                    this._seo.setTitle(response.name)
                    this._seo.updateTag('description', response.description)
                }),
                map((response) => {
                
                    // If we're checking for quantity, disable all products from the beginning
                    if(this.checkQuantity) {

                        for(let product of response.products) {
                            this.productQuantityStateMap.set(product.sku, false)
                        }
                    }

                    return response
                })
            )
            .subscribe({
                next: (categoryData) => {
                    this.category = categoryData

                    // If quantity is maintained, validate and find the amount
                    if(this.checkQuantity) {
                        this._validateQuantity()
                    }

                    this.loadingSource.next(false)
                },
                error: e => {

                    this.loadingSource.next(false)
                    console.error(e)
                }
            })
    }


    /**
     * Finds `modifier` to element, based on the `display_shape`
     * 
     * @param string
     * @returns string
     */
    getClassShape(string: string): string {

        let shape

        switch(string) {
            case 'Rectangular':
                shape = 'mod--rectangle'
                break
            case 'Big':
                shape = 'mod--big'
                break
            default:
                shape  = ''
                break
        }

        return shape
    }


    /**
     * Finds `shape` for ngClass based on the `display_shape`
     * 
     * @param string
     * @returns string
     */
    getClassSize(string: string): string {

        let size

        switch(string) {
            case 'Rectangular':
                size = 'size-6 size-12--lap size-12--palm'
                break
            case 'Big':
                size = 'size-6 size-12--lap size-12--palm'
                break
            default:
                size = 'size-3 size-6--lap size-6--palm'
                break
        }

        return size
    }


    /**
     * Calculates how many products to display, using slice pipe, stolen from SO, as it felt like a
     * great example, however, the math behind is, is not something I'm confident in.
     * 
     * @source https://stackoverflow.com/questions/45318164/how-to-use-paginator-from-material-angular
     * @param event 
     */
    getPaginatorData(event) {

        if(event.pageIndex === this.pageIndex + 1) {
            this.lowValue = this.lowValue + this.pageSize;
            this.highValue =  this.highValue + this.pageSize;
        }
        else if(event.pageIndex === this.pageIndex - 1) {
            this.lowValue = this.lowValue - this.pageSize;
            this.highValue =  this.highValue - this.pageSize;
        }   
        
        this.pageIndex = event.pageIndex;
    }

    // PRIVATE

    /**
     * Gets quantity from the category service and populates the map with true values, for products that have a quantity higher than 0
     */
    private _validateQuantity() {
        this.categoryService.getQuantity(Array.from(this.productQuantityStateMap.keys())).subscribe((response) => {

            let products = response || []

            // Iterate response and find quantity higher than 0
            for(let product of products) {
                if(product.qty > 0)
                    this.productQuantityStateMap.set(product.sku, true)
            }
        })
    }
}

