Refactor this code to be more modern and clean import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';
import { ModalConfig, ModalComponent } from '../../_metronic/partials';
import { ErrorMatch, matchPreferences, MatchService, USER_PER_PAGE, UserSuggestionType } from 'src/app/services/Api/match.service';
import { Observable, Subscription } from 'rxjs';
import { UserType } from 'src/app/modules/auth';
import { LoadingService } from 'src/app/services/Api/loading.service';
import { SwalComponent } from '@sweetalert2/ngx-sweetalert2';
import * as bootstrap from 'bootstrap';
import Tagify from '@yaireo/tagify';
import { FormControl, FormGroup } from '@angular/forms';

declare let Swiper: any;

@Component({
  selector: 'app-match',
  templateUrl: './match.component.html',
  styleUrls: ['./match.component.scss'],
})
export class MatchComponent implements OnInit, OnDestroy, AfterViewInit {

  subscriptions: Subscription[] = [];
  swiper: any;
  users: UserSuggestionType[] = [];
  page: number = 0;
  firstCall = true;
  currentIndex = 0;
  isLoading = false;
  isLoadingPreferences = false;
  lastCallEmpty = false;
  swipesLeft: number = 0;
  intervalSwipes: any;
  matchingUserSuggestion$: Observable<boolean>;
  matchingError: UserType;
  @ViewChild('lastMatch') lastMatch: SwalComponent;
  preferencesForm: FormGroup;
  ageRangeMin = 50;
  ageRangeMax = 50;

  constructor(private matchService: MatchService, private cdr: ChangeDetectorRef, private loadingService: LoadingService) {
    this.matchingUserSuggestion$ = this.loadingService.getLoading('user-suggestions', 'match');

    this.preferencesForm = new FormGroup({
      minAge: new FormControl(50),
      maxAge: new FormControl(50),
      academicTitle: new FormControl(''),
      attributes: new FormControl(),
    })
  }

  ngOnInit(): void {
    this.getUserSuggestions();
    this.getPreferences();

    this.matchingUserSuggestion$.subscribe({
      next: (loadingState) => {
        this.isLoading = loadingState;
        this.cdr.detectChanges();
      }
    })
    this.swiper = new Swiper('.blog-slider', {
      effect: 'fade',
      oneWayMovement: true,
      observer: true,
      loop: false,
      mousewheel: false,
      /*pagination: {
        el: '.blog-slider__pagination',
        clickable: true,
      },*/
      grabCursor: true,
      shortSwipes: false,
      on: {
        touchStart: (e: any) => {
          this.currentIndex = e.activeIndex;
        },
        touchEnd: (e: any) => {
          if(this.currentIndex !== e.activeIndex) {

          const swipeDirection = this.getSwipeDirection(e.touches.previousX, e.touches.currentX);
          this.currentIndex = e.activeIndex;
          if(swipeDirection === 'prev'){
            this.swipeLeft(e.previousIndex);
          }
          else if(swipeDirection === 'next'){
            this.swipeRight(e.previousIndex);
          }
          if(!this.lastCallEmpty && this.currentIndex === e.slides.length-2){
            this.page++;
            this.getUserSuggestions();
          }
          this.cdr.detectChanges();
          }
        },

      }
    });

  }

  ngAfterViewInit(): void {
    this.setSkillsElem();
    this.subscribetoMatches();
    this.subscribetoErrorMatches();
    this.getSwipesAllowed();
    this.intervalSwipes = setInterval(() => {
      this.getSwipesAllowed();
    }, 600000)
  }

  subscribetoMatches(){
    this.subscriptions.push(this.matchService.userMatches$.subscribe({
      next: (userMatched: UserType | null) => {
      if(userMatched){
      this.fireLastMatch(userMatched);
      }},
      error: (error) => {
        console.error(error);
      }
    }))
  }

  subscribetoErrorMatches(){
    this.subscriptions.push(this.matchService.userErrorMatches$.subscribe((errorMatched: UserType | null) => {
      if(errorMatched){
        this.matchingError = errorMatched;
        this.swipesLeft++;
        this.cdr.detectChanges();
        const toastElement = document.querySelector('#kt_docs_toast_toggle');
        const toast = bootstrap.Toast.getOrCreateInstance(toastElement as string | Element);
        toast.show();
      }
    }))
  }

  fireLastMatch(userMatched: UserType){
    this.lastMatch.swalOptions = {
      title: "It's a match!",
      text: userMatched?.firstName + ' ' + userMatched?.lastName + ' liked your profile too!',
      imageUrl: userMatched?.photo,
      imageWidth: 200,
      imageHeight: 200,
      imageAlt: "Matched User Image",
      showCancelButton: true,
      cancelButtonText: 'Ok, got it!',
      confirmButtonText: 'Send a Message',
      buttonsStyling: false,
      customClass: {
        confirmButton: 'btn btn-primary',
        cancelButton: 'btn btn-secondary',
        image: 'rounded img-thumbnail'
      },
    };
    this.lastMatch.fire();
  }

  getSwipesAllowed(){
      this.subscriptions.push(this.matchService.getSwipesAllowed().subscribe({
        next: (response) => {
          this.swipesLeft = response;
          this.cdr.detectChanges();
          if(this.swipesLeft === 0){
            this.swiper.disable();
          }
          else{
            this.swiper.enable();
          }
        },
        error: (error) => {
          console.error(error);
        }
      }))

  }

  swipeLeft(index: number){
    this.matchService.markAsDislike(this.users[index].user?.id!);
    this.swipesLeft--;
    if(this.swipesLeft === 0){
      this.swiper.disable();
    }
    else{
      this.swiper.enable();
    }
  }

  swipeRight(index: number){
    this.matchService.markAsLike(this.users[index].user?.id!);
    this.swipesLeft--;
    if(this.swipesLeft === 0){
      this.swiper.disable();
    }
    else{
      this.swiper.enable();
    }
    //this.users.splice(0,1);
    //this.cdr.detectChanges();
    //this.swiper.update();

  }

  getSwipeDirection(startX: number, endX: number): string {
    const diff = endX - startX;

    if (diff > 0) {
        return 'prev';
    }
    else if (diff < 0) {
        return 'next';
    }
    else {
        return 'none';
    }
}

  getUserSuggestions(){
    this.clearSubscriptions()
    this.loadingService.startLoading('user-suggestions', 'match');
    this.subscriptions.push(this.matchService.getUserSuggestions(this.page).subscribe({
      next: (data) => {
        console.log(data);
      if(data.length === 0 || (this.firstCall && data.length<=2 && data.length>0)){
        if(this.firstCall){
          this.firstCall = false;
        }
        if(data.length>0){
          data.forEach((suggestion) => {
            this.users.push(suggestion);
            this.cdr.detectChanges();
            this.swiper.update();
          })
        }
        this.lastCallEmpty = true;
        this.swiper.appendSlide(`<div class="blog-slider__item swiper-slide"></div>`);
        this.cdr.detectChanges();
        this.swiper.update();
      }
      else{
      data.forEach((suggestion) => {
        this.users.push(suggestion);
        this.cdr.detectChanges();
        this.swiper.update();
      })
    }
      this.loadingService.stopLoading('user-suggestions', 'match');
    },
    error: (error) => {
      console.error(error);
      this.loadingService.stopLoading('user-suggestions', 'match');
    }
  }));
  }

  setSkillsElem(){
    let attributesElem = document.querySelector('#attributes') as HTMLInputElement; // the 'input' element which will be transformed into a Tagify component

    let attributes = new Tagify(attributesElem, {
      pattern: /^.{3,20}$/, // Validate typed tag(s) by Regex. Here maximum chars length is defined as "20"
      delimiters: ',| ', // add new tags when a comma or a space character is entered
      trim: false, // if "delimiters" setting is using space as a delimeter, then "trim" should be set to "false"
      keepInvalidTags: false, // do not remove invalid tags (but keep them marked as invalid)
      editTags: {
        clicks: 2, // single click to edit a tag
        keepInvalid: false, // if after editing, tag is invalid, auto-revert
      },
      maxTags: 6,
      blacklist: ['foo', 'bar', 'baz'],
      whitelist: [
        'temple',
        'stun',
        'detective',
        'sign',
        'passion',
        'routine',
        'deck',
        'discriminate',
        'relaxation',
        'fraud',
        'attractive',
        'soft',
        'forecast',
        'point',
        'thank',
        'stage',
      ],
      backspace: 'edit',
      placeholder: 'Let us know your preferred attributes. Max 6',
      dropdown: {
        enabled: 1, // show suggestion after 1 typed character
        fuzzySearch: false, // match only suggestions that starts with the typed characters
        position: 'text', // position suggestions list next to typed text
        caseSensitive: true, // allow adding duplicate items if their case is different
      },
      templates: {
        dropdownItemNoMatch: function (data) {
          return `<div class='${this.settings.classNames.dropdownItem}' value="noMatch" tabindex="0" role="option">No suggestion found for: <strong>${data.value}</strong></div>`;
        },
      },
    });

    //Prepopulation
    let initialAttributes = this.preferencesForm.get('attributes')?.value;

    if (initialAttributes && initialAttributes.length > 0) {
        attributes.addTags(initialAttributes);
    }

    attributesElem.addEventListener('change', () => {
      let patch = attributes.value.map(e => e.value);
      this.preferencesForm.patchValue({ attributes: patch });
    });
  }

  getPreferences(){
    this.subscriptions.push(this.matchService.getPreferences().subscribe({
      next: (response) => {
        this.preferencesForm.patchValue({
          maxAge: response.maxAge,
          minAge: response.minAge,
          academicTitle: response.academicLevel,
          attributes: response.attributes
        })
        this.ageRangeMax = response.maxAge;
        this.ageRangeMin = response.minAge;
      },
      error: (error) => {
        console.error(error);
      }
    }))
  }

  savePreferences(){
    this.isLoadingPreferences = true;
    let matchingPreferences: matchPreferences = {
      maxAge: this.preferencesForm.value.maxAge,
      minAge: this.preferencesForm.value.minAge,
      academicLevel: this.preferencesForm.value.academicTitle,
      attributes: this.preferencesForm.value.attributes
    };
    this.subscriptions.push(this.matchService.setPreferences(matchingPreferences).subscribe({
      next: () => {
        this.isLoadingPreferences = false;
        this.page = 0;
        this.getUserSuggestions();
        this.cdr.detectChanges();
      },
      error: (error) => {
        this.isLoadingPreferences = false;
        this.cdr.detectChanges();
        console.error(error);
      }
    }
    ))
  }

  updateValueRange(e: any){
    if(e.target.classList.contains('max-age')){
      this.ageRangeMax = e.target.value
    }
    else if(e.target.classList.contains('min-age')){
      this.ageRangeMin = e.target.value
    }
  }

  private clearSubscriptions(){
    this.subscriptions.forEach(sb => sb.unsubscribe())
  }

  ngOnDestroy(): void {
    this.clearSubscriptions;
    clearInterval(this.intervalSwipes);
  }



}