/*
 * Copyright (C) 2023 Robert Bosch GmbH Copyright (C) 2023 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import {Component, EventEmitter, Input, OnInit, Output, HostListener, ElementRef} from '@angular/core';
import {MatIconModule} from "@angular/material/icon";
import {FormsModule} from "@angular/forms";

/**
 * The BciNumberPicker component provides a complex solution for picking a number.
 * You can pick a number in the following ways:
 *  - clicking up and down arrows
 *  - using keyboard arrows
 *  - using mouse wheel
 *
 * The component can follow a loop by having a min and max value.
 */
@Component({
  standalone: true,
  selector: 'bci-number-picker',
  templateUrl: './bci-number-picker.component.html',
  styleUrls: ['./bci-number-picker.component.scss'],
  imports: [
    MatIconModule,
    FormsModule,
  ]
})
export class BciNumberPickerComponent implements OnInit{
  /**
   * Defines the existing value. Factory set to be 0.
   */
  @Input() value = 0;

  /**
   * Defines a specified min limit for numbers. Factory set to be 0.
   */
  @Input() minValue = 0;

  /**
   * Defines a specified maximum limit for numbers. If not defined, no range is applied.
   */
  @Input() maxValue: number;

  /**
   * Propagates the new selected value.
   */
  @Output() selectedValue: EventEmitter<number> = new EventEmitter<number>();

  @HostListener('window:keydown', ['$event']) onKeyPress(event: KeyboardEvent): void {
    if(this.elementRef.nativeElement.contains(event.target) && document.activeElement === event.target) {
      if(event.key === 'ArrowUp'){
        event.preventDefault();
        this.increase();
      }
      if(event.key === 'ArrowDown'){
        event.preventDefault();
        this.decrease();
      }
    }
  }

  constructor(private elementRef: ElementRef) {}

  ngOnInit(): void {
    this.checkAndFitToRange();
  }

  increase(): void {
    this.handleValue(Number(this.value) + 1);
    this.emitValue();
  }

  decrease(): void {
    this.handleValue(this.value - 1);
    this.emitValue();
  }

  onBlur(): void {
    this.checkAndFitToRange();
  }

  handleScroll(event: WheelEvent): void {
    if (this.elementRef.nativeElement.contains(event.target) && document.activeElement === event.target) {
      if (event.deltaY > 0) {
        // Scrolling down
        this.decrease();
      } else {
        // Scrolling up
        this.increase();
      }
      event.preventDefault(); // Prevent the default scrolling behavior
    }
  }

  checkAndFitToRange(): void {
    if (this.value > this.maxValue) {
      console.warn('Number picker value bigger then maxValue set!');
      this.value = this.maxValue;
    }

    if (this.value < this.minValue) {
      console.warn('Number picker value smaller then minValue set!');
      this.value = this.minValue;
    }

    this.emitValue();
  }

  private handleValue(newValue: number): void {
    if(this.maxValue) {
      if(newValue < this.minValue) {
        this.value = this.maxValue;
        return;
      }
      if(newValue > this.maxValue) {
        this.value = this.minValue;
        return;
      }
      this.value = newValue;
    } else {
      newValue >= this.minValue ? this.value = newValue : this.value = this.minValue;
    }
  }

  private emitValue(): void {
    this.selectedValue.emit(this.value);
  }
}
