// Angular Core
import { Component, OnInit, OnDestroy, Renderer2, ElementRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { Router } from '@angular/router';
import { HttpErrorResponse } from '@angular/common/http';

// RxJs
import { Subscription, throwError } from 'rxjs';
import { catchError } from "rxjs/operators";

// Pipes
import { DetectApostrophePipe } from 'src/app/filters/detect-apostrophe.pipe';

// Services
import { CartService } from 'src/app/services/cart/cart.service';
import { CartValidationService } from 'src/app/services/cartValidation/cart-validation.service';
import { SupplierCatalogService } from 'src/app/services/supplierCatalog/supplier-catalog.service';

// Models
import { quickcartDataModel } from './quickcartData.model';
import { environment } from 'src/environments/environment';

interface ButtonText {
  [index: number] : string
}

@Component({
  standalone: false,
  selector: 'app-quick-cart',
  templateUrl: './quick-cart.component.html',
  styleUrls: ['./quick-cart.component.scss', './quick-cart.component.query.scss'],
  encapsulation: ViewEncapsulation.None,
})
export class QuickCartComponent implements OnInit, OnDestroy {

  @ViewChild('view_cart_collapse') view_cart_collapse!: ElementRef;
  @ViewChild('view_cart_button') view_cart_button!: ElementRef;
  imgUrl: string = environment.imageUrl;
  quickCartEvent!: Subscription;

  constructor(
    private cartService: CartService,
    private supplierCatalogService: SupplierCatalogService,
    private cartValidationService: CartValidationService,
    private detectApostrophe:DetectApostrophePipe,
    private router: Router,
    private renderer: Renderer2
  ) { 
      /**
         * This events get called by all clicks on the page
         */
      this.renderer.listen('window', 'click',(e:Event)=>{
        /**
         * Only run when toggleButton is not clicked
         * If we don't check this, all clicks (even on the toggle button) gets into this
         * section which in the result we might never see the menu open!
         * And the menu itself is checked here, and it's where we check just outside of
         * the menu and button the condition abbove must close the menu
         */
        if(this.isCollapsed === true && (!this.view_cart_collapse.nativeElement.contains(e.target)) && (!this.view_cart_button.nativeElement.contains(e.target))){
            this.isCollapsed=false;
        }
      });
    }

  ngOnInit(): void {
    /**
     * Trigger when refreshing the quickcart popover
     */
    this.quickCartEvent = this.cartService.QuickCart.subscribe((data: any) => {
        if(data === '') {
        this.quickcartContent();
        } else {
            this.quickcartData.data = data;
        }
    });
    this.quickcartContent();
  }

  public isCollapsed = false;
  itemsCollapsed:boolean[] = [];
  
  /**
   * data model for getting cart content in quick cart
   */
  quickcartData:quickcartDataModel = {
    data: []
  };
  
  bestShippingMethod!:any;

  getShoppingCartSubscribe!:Subscription;
  removeFromCartSubscribe!:Subscription;
  /**
   * call cart service
   * @return {undefined}
   */
  quickcartContent() {
    this.getShoppingCartSubscribe = this.cartService.getShoppingCart()
      .pipe(
        catchError(() => {
          return throwError(() => new Error('ups sommething happend'));
        })
      )
      .subscribe({
        next: (res: any) => {
          this.quickcartData.data = res.data;
          this.setDefault(this.quickcartData.data);
        },
        error: (err: HttpErrorResponse) => {
          this.cartService.errorCallBack(err);
        },
        complete: () => { }
      });
  };
  /**
   * check number of characters and truncate text if greater than 40
   * @param {type} text
   * @return {Boolean}
   */
  isLonger(text: any) {
    if (typeof text === 'string') {
      return text.length > 40;
    } else {
      return false;
    }
  };

  checkCutOff(supplierCutOffTime:string) {
      if (supplierCutOffTime !== '' && supplierCutOffTime !== undefined && supplierCutOffTime !== null) {
          var estOffset = this.cartService.getEstOffset();
          //Get the current time in milliseconds with regards to supplier's time zone
          var now = new Date();
          var d = new Date();
          var d_sethours:any = d.setHours(now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds())
          var d_sethours_in_int = parseInt(d_sethours)
          var d_get_timezone_offset:any = d.getTimezoneOffset() * 60 * 1000
          var time = d_sethours_in_int + parseInt(d_get_timezone_offset);
          var userConvertedTime = (time - estOffset);
          //Get the cut off time in milliseconds
          var supplierCutOff:any = this.cartService.getSupplierCutOffTimeObj(estOffset, supplierCutOffTime);
          var diff:any = 0;
          diff = supplierCutOff - userConvertedTime;
          diff = parseInt(diff)
          if (!(diff > 0)) {
              return true;
          }
      }
      return false;
};

  /**
   * Remove Item from Quick Cart
   * @param {type} auctionId
   * @return {undefined}
   */
  removeItemQuickCart(auctionId: number) {
    this.removeFromCartSubscribe = this.cartService.removeFromCart(auctionId)
      .pipe(
        catchError(() => {
          return throwError(() => new Error('ups sommething happend'));
        })
      )
      .subscribe({
        next: (res: any) => {
          //get cart data
          this.quickcartContent();
          //refresh quick cart
          this.cartService.RefreshQuickCart.emit('');
        },
        error: (err: HttpErrorResponse) => {
          this.cartService.errorCallBack(err);
        },
        complete: () => { }
      });
  };
  /**
  * redirect user to supplier search results page with passed values
  */
  supplierCatalogSearch(supplierName: string, supplierId: number) {
    supplierName = this.detectApostrophe.transform(supplierName)
    this.supplierCatalogService.setSupplierId(supplierId);

    this.router.navigate(['/market/supplierCatalog'], { queryParams: { supplierName: escape(supplierName), supplierId: supplierId, mdl: 'mp' } });
    setTimeout(() => {
        this.supplierCatalogService.emitSupplierCatalogOnSamePage({
            name: supplierName,
            supplierId: supplierId,
        });  
    }, 1000);        
    this.isCollapsed=false;
  };
  /**
  * Logic to find the fastest shipping method with minimum met
  * @returns {undefined}
  */
  setDefault(cartData: any) {
    cartData = Object.keys(cartData).map(key => cartData[key])
    cartData.forEach((supplier: any, index:number) => {
      this.buttonText[index] = ' Hide Items';    
      this.buttonIcon[index] = this.imgUrl+'/up.png';
      this.bestShippingMethod = '';
      Object.keys(supplier.shippingData.shipping_methods).forEach((key: string, index: number) => {
        supplier.shippingData
        .shipping_methods[key].selected = false;
        if (supplier.shippingData.shipping_methods[key].status === 'Minimum Met') {
          this.bestShippingMethod = supplier.shippingData.shipping_methods[key];
        }
      });
      if (this.bestShippingMethod !== '') {
        this.setShippingMethod(this.bestShippingMethod, supplier);
      }
    });
  };

  /**
  * Sets the shipping method
  * @param {type} supplier
  * @param {type} method
  * @return {undefined}
  */
  setShippingMethod(method: any, supplier: any) {
    method.selected = true;
    supplier.shippingData.selectedShipping = method.name;
    if (method.status === 'Not Met') {
      supplier.shippingData.shippingFee = method.feeForMinOrder;
    }
    else if (method.status === 'Minimum Met') {
      supplier.shippingData.shippingFee = 0;
    }
    this.cartValidationService.validateShipping(supplier);
  };

  /**
   * Sets the selected property of shipping methods initially to false
   * @param {type} methods
   * @return {undefined}
   */
  setFlag(methods: any) {
    var flag = false;
    methods.forEach((obj: any) => {
      obj.selected = flag;
    });
  };
  
  /**
  * Sets the shipping method as selected
  * @param {type} supplier
  * @param {type} method
  * @return {undefined}
  */
  setSelected(supplier: any, method: any) {
    supplier.shippingData.shipping_methods = Object.keys(supplier.shippingData.shipping_methods).map(key => supplier.shippingData.shipping_methods[key]);
    this.setFlag(supplier.shippingData.shipping_methods);
    method.selected = true;
    supplier.shippingData.selectedShipping = method.name;
    if (method.status === 'Not Met') {
      supplier.shippingData.shippingFee = method.feeForMinOrder;
    }
    else if (method.status === 'Minimum Met') {
      supplier.shippingData.shippingFee = 0;
    }
    this.cartValidationService.validateShipping(supplier);
  };

  buttonText: ButtonText = {};
  buttonIcon: ButtonText = {};
  collapseItem(index: number){
    this.itemsCollapsed[index] = !this.itemsCollapsed[index];
    this.itemsCollapsed[index] ? this.buttonText[index] = ' Show Items' : this.buttonText[index] = ' Hide Items';
    this.itemsCollapsed[index] ? this.buttonIcon[index] = this.imgUrl+'/down.png' : this.buttonIcon[index] = this.imgUrl+'/up.png';
  }

  // Trackby function for track looping items
  trackByFn(index:number, item:any){
    return item.key
  }

  // Unbind page data when controller is destroyed to avoid memory leak
  ngOnDestroy(){
    this.getShoppingCartSubscribe?.unsubscribe();
    this.removeFromCartSubscribe?.unsubscribe();
    this.quickCartEvent?.unsubscribe();
  }

}
