import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { LanguageService } from '@shared/language/language.service';
import { ConfigService } from '@shared/config/config.service';

@Directive({
  selector: '[appLayoutGap]'
})
export class LayoutGapDirective implements AfterViewInit, OnDestroy {
  @Input() appLayoutGap: string;
  @Input() xsGap: string = null;
  @Input() smGap: string = null;
  currentBreakPoint;
  breakpointSubscription: Subscription;
  private defaultSet = false;

  constructor(
    private elementRef: ElementRef,
    private languageService: LanguageService,
    private config: ConfigService,
  ) { }

  setDefault(breakpoint) {
    if (this.currentBreakPoint !== breakpoint) {
      this.currentBreakPoint = breakpoint;
      this.setGaps(this.appLayoutGap);
      this.defaultSet = true;
    }
  }

  ngAfterViewInit() {
    if (this.config.appBreakpointObservable) {
      this.breakpointSubscription = this.config.appBreakpointObservable.subscribe(breakpoint => {
        switch (breakpoint) {
          case 'xs':
            if (this.xsGap !== null && this.currentBreakPoint !== 'xs') {
              this.currentBreakPoint = 'xs';
              this.setGaps(this.xsGap);
              this.defaultSet = false;
            } else {
              this.setDefault(breakpoint);
            }
            break;
          case 'sm':
            if (this.smGap !== null && this.currentBreakPoint !== 'sm') {
              this.currentBreakPoint = 'sm';
              this.setGaps(this.smGap);
              this.defaultSet = false;
            } else {
              this.setDefault(breakpoint);
            }
            break;
          default:
            this.setDefault(breakpoint);
        }
      });
    }
  }

  private setGaps(gap) {
    if (gap) {
      const children = this.elementRef.nativeElement.children as HTMLCollection;
      let index = 0;
      while (index < children.length) {
        const element = children.item(index) as HTMLElement;

        const parentDirection = element.parentElement.attributes.getNamedItem('layoutdirection');
        const parentDirectionXs = element.parentElement.attributes.getNamedItem('layoutdirection-xs');
        const parentDirectionLtSm = element.parentElement.attributes.getNamedItem('layoutdirection-lt-sm');
        const parentDirectionLtMd = element.parentElement.attributes.getNamedItem('layoutdirection-lt-md');
        let updateVertically: boolean;
        switch (this.currentBreakPoint) {
          case 'xs':
            updateVertically = (
              parentDirection?.value === 'column' || parentDirectionXs?.value === 'column' ||
              parentDirectionLtSm?.value === 'column' || parentDirectionLtMd?.value === 'column'
            );
            break;
          case 'sm':
            updateVertically = parentDirection?.value === 'column' || parentDirectionLtMd?.value === 'column';
            break;
          default:
            updateVertically = parentDirection?.value === 'column';
        }

        if (index !== (children.length - 1) || children.length === 1) {
          if (updateVertically) {
            element.style.marginBottom = gap;
            if (this.languageService.isRtlLanguage()) {
              element.style.marginLeft = 'unset';
            } else {
              element.style.marginRight = 'unset';
            }
          } else {
            if (this.languageService.isRtlLanguage()) {
              element.style.marginLeft = gap;
            } else {
              element.style.marginRight = gap;
            }
            element.style.marginBottom = 'unset';
          }
        }

        index += 1;
      }
    }
  }

  ngOnDestroy() {
    if (this.breakpointSubscription) {
      this.breakpointSubscription.unsubscribe();
      this.breakpointSubscription = null;
    }
  }

}
