// NG Imports
import { Directive, Input, AfterContentInit, ElementRef, ApplicationRef, ChangeDetectorRef, Renderer2, PLATFORM_ID, Inject } from '@angular/core'
import { isPlatformBrowser } from '@angular/common'

// Helpers
import { cookiebotId } from '@k-settings/app-setup'

// Services
import { CookieBotService } from '@k-services/general/svc.cookieBot'

// Pipes
import { TranslatePipe } from '@k-core/pipes/pipe.translate'



@Directive({
    selector: 'iframe'
})
export class videoConsentDirective implements AfterContentInit {

    // ---- EXTERNAL VARIABLES ---- \\

    @Input() src: string


    // ---- LOCAL VARIABLES ---- \\
    
    promiseInterval: any
    cookieBotSubscription: any
    cookieBotValues: any
    show_warning: boolean = true

    // Add iframe sources that needs to be blacklisted without marketing enabled
    blacklistMarketing: string[] = ['youtu', 'mistia']
    blacklistStatistics: string[] = ['vimeo']







    constructor(
        @Inject(PLATFORM_ID) private _platformId,
        private elRef: ElementRef,
        private _cookieBot: CookieBotService,
        private _translate: TranslatePipe,
        private renderer: Renderer2
    ) {
        this.cookieBotSubscription = _cookieBot.cookieBot$.subscribe((response) => {

            // Makes sure interval is cleared before booting up a second one
            clearInterval(this.promiseInterval)

            // Storing the response in a variable
            console.log('cookebot values', response)
            this.cookieBotValues = response

            this.checkVideoState()
        })
    }





    // ---- Lifecycle hooks ---- \\


    // After the content is loaded, decide what to do with the iframe
    ngAfterContentInit() {
        if(isPlatformBrowser(this._platformId))
            this.checkVideoState()
    }


    // Unsubscribes to limit the overflow
    ngOnDestroy() {
        this.cookieBotSubscription.unsubscribe()
    }






    // ---- FUNCTIONS ----\\

    /**
     * Promise to handle if the cookiebot values are set before initialiing the run of data
     */
    checkVideoState() {

        // Only run if CookieBot is available
        if(!!cookiebotId) {

            let checkState = ''
            if(!!this.src) {
    
                if(typeof this.src == 'object') {
                    
                    console.log('object found, manipulate it to get source')
                    let value:any = this.src
    
                    this.src = value.changingThisBreaksApplicationSecurity
                } else {
                    
                    if(this.src.includes('vimeo')) {
                        checkState = 'statistics'
                    } else if(this.src.includes('youtu')) {
                        checkState = 'marketing'
                    }
                }
        
                new Promise(resolve => {
        
                    this.promiseInterval = setInterval(() => {
        
                        if(this._cookieBot.cookieBotConsentValue(checkState) !== undefined) {
                            clearInterval(this.promiseInterval)
                            resolve(checkState)
                        }
                        
                    }, 100)
                }).then((response: string) => {
        
                    console.log('Check state promise', response)
                    this.modifyTag(response)
                })
            }
        }
        else {
            // show warning about missing cookiebot id. But only once, to avoid spam
            if(this.show_warning) {
                console.warn('no cookiebot id found')
                this.show_warning = false
            }
        }
        
    }




    /**
     * Appends cookie warning element
     */
    Element(mode: string) {


        if(isPlatformBrowser(this._platformId)) {

            const element = this.renderer.createElement('a')
    
            // Creates the text to inject into the element, translates it before it's injected
            const text = this.renderer.createText(this._translate.transform('Renew or change your cookie consent'))
    
            // Sets styling class
            this.renderer.addClass(element, 'cookiebot-renew')
    
            // Sets HREF
            // this.renderer.setAttribute(element, 'href', '#')
    
            // Sets onClick
            this.renderer.setAttribute(element, 'onclick', 'javascript:Cookiebot.renew(); return false;')
    
            // Appends everything
            this.renderer.appendChild(element, text)
        
            const parent = this.elRef.nativeElement.parentNode
            const refChild = this.elRef.nativeElement
            
            // Renders the element
            if(mode == 'insert') {
    
                this.renderer.insertBefore(parent, element, refChild)
            }
            else if(mode == 'destroy') {
    
                // Removes the cookiebot-renew class that makes the element visible
                for(let child of parent.children) {
                    if(child.className.includes('cookiebot-renew')) {
    
                        this.renderer.removeClass(child, 'cookiebot-renew')
                        this.renderer.addClass(child, 'cookiebot-remove-text')
                    }
                }
            }
        }
    }
    



    /**
     * Modifies the tags based on `statistics` or `marketing` attribute fed through `tag`
     * 
     * @param tag marketing | statistics
     */
    modifyTag(tag) {

        if(isPlatformBrowser(this._platformId)) {
            
    
            const elementRef = this.elRef.nativeElement
    
            if(tag == 'marketing' && !this._cookieBot.cookieBotConsentValue('marketing')) {
    
                if(this.isBlacklistedMarketing(this.src)) {
    
                    
                    this.renderer.addClass(elementRef, 'disabled')
                    this.renderer.setAttribute(elementRef, 'data-src', this.src)
                    
                    this.Element('insert')
    
                } else {
    
                    this.renderer.removeClass(elementRef, 'disabled')
                    this.renderer.setAttribute(elementRef, 'src', elementRef.getAttribute('data-src'))
                    this.renderer.removeAttribute(elementRef, 'data-src')
    
                    this.Element('destroy')
                }
            } else if(tag == 'statistics' && !this._cookieBot.cookieBotConsentValue('statistics')) {
    
                
    
                if(this.isBlacklistedStatistics(this.src)) {
    
    
                    this.renderer.addClass(elementRef, 'disabled')
                    this.renderer.setAttribute(elementRef, 'data-src', this.src)
    
    
                    this.Element('insert')
    
                } else {
    
                    console.log('should attempt to destroy')
    
                    this.renderer.removeClass(elementRef, 'disabled')
                    this.renderer.setAttribute(elementRef, 'src', elementRef.getAttribute('data-src'))
                    this.renderer.removeAttribute(elementRef, 'data-src')
                    
                    this.Element('destroy')
                }
        
            } else {
    
                this.renderer.removeClass(elementRef, 'disabled')
                this.renderer.setAttribute(elementRef, 'src', this.src)
    
                this.Element('destroy')
            }
        }
    }




    /**
     * Validates if the source of iframe needs to be cookie handled or not,if it is
     *  set for blacklisting it will not display the iframe contents.
     * 
     * @requires blacklist[]
     * @param string contains: youtu | vimeo | mistia
     * @returns {boolean} true | false
     */
    isBlacklistedMarketing(string: string): boolean {

        let result = false

        // iterates the values of blacklist, to see if source is inside
        for(let str of this.blacklistMarketing) {
            if(string.includes(str))
                result = true
        }

        return result
    }



    /**
     * Validates if the source of iframe needs to be cookie handled or not,if it is
     *  set for blacklisting it will not display the iframe contents.
     * 
     * @requires blacklist[]
     * @param string contains: youtu | vimeo | mistia
     * @returns {boolean} true | false
     */
    isBlacklistedStatistics(string: string): boolean {

        let result = false

        // iterates the values of blacklist, to see if source is inside
        for(let str of this.blacklistStatistics) {
            if(string.includes(str))
                result = true
        }

        return result
    }
}