/*
 * Copyright (C) 2018-2021 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {Component, Input, OnInit, OnDestroy} from '@angular/core';
import {Router} from '@angular/router';
import {AlertController} from '@ionic/angular';
import {NGXLogger} from 'ngx-logger';
import {combineLatest} from 'rxjs';
import {debounceTime, distinctUntilChanged, startWith} from 'rxjs/operators';
import {ContextMenuService} from '../../menu/context/context-menu.service';
import {SettingsProvider} from '../../settings/settings.provider';
import {DataRoutingService} from '../../data/data-routing.service';
import {SearchPageComponent} from '../../data/list/search-page.component';
import {HebisDataProvider} from '../hebis-data.provider';
import {PositionService} from '../../map/position.service';

/**
 * HebisSearchPageComponent queries things and shows list of things as search results and filter as context menu
 */
@Component({
  selector: 'stapps-hebissearch-page',
  templateUrl: 'hebis-search-page.html',
})
export class HebisSearchPageComponent
  extends SearchPageComponent
  implements OnInit, OnDestroy
{
  /**
   * If routing should be done if the user clicks on an item
   */
  @Input() itemRouting? = true;

  /**
   * Current page to start query
   */
  page = 0;

  /**
   * Injects the providers and creates subscriptions
   *
   * @param alertController AlertController
   * @param dataProvider HebisProvider
   * @param contextMenuService ContextMenuService
   * @param settingsProvider SettingsProvider
   * @param logger An angular logger
   * @param dataRoutingService DataRoutingService
   * @param router Router
   * @param positionService PositionService
   */
  constructor(
    protected readonly alertController: AlertController,
    protected dataProvider: HebisDataProvider,
    protected readonly contextMenuService: ContextMenuService,
    protected readonly settingsProvider: SettingsProvider,
    protected readonly logger: NGXLogger,
    protected dataRoutingService: DataRoutingService,
    protected router: Router,
    protected positionService: PositionService,
  ) {
    super(
      alertController,
      dataProvider,
      contextMenuService,
      settingsProvider,
      logger,
      dataRoutingService,
      router,
      positionService,
    );
  }

  /**
   * Fetches items with set query configuration
   *
   * @param append If true fetched data gets appended to existing, override otherwise (default false)
   */
  protected async fetchAndUpdateItems(append = false): Promise<void> {
    // build query search options
    const searchOptions: {page: number; query: string} = {
      page: this.page,
      query: '',
    };

    if (this.queryText && this.queryText.length > 0) {
      // add query string
      searchOptions.query = this.queryText;
    }

    return this.dataProvider.hebisSearch(searchOptions).then(
      async result => {
        /*this.singleTypeResponse =
          result.facets.find(facet => facet.field === 'type')?.buckets
            .length === 1;*/
        if (append) {
          let items = await this.items;
          // append results
          items = [...items, ...result.data];
          this.items = (async () => items)();
        } else {
          // override items with results
          this.items = (async () => {
            return result.data;
          })();
        }
      },
      async error => {
        const alert: HTMLIonAlertElement = await this.alertController.create({
          buttons: ['Dismiss'],
          header: 'Error',
          subHeader: error.message,
        });

        await alert.present();
      },
    );
  }

  /**
   * Loads next page of things
   */
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  async loadMore(): Promise<void> {
    this.page += 1;
    await this.fetchAndUpdateItems(true);
  }

  ngOnInit() {
    //this.fetchAndUpdateItems();
    this.initialize();

    this.subscriptions.push(
      combineLatest([
        this.queryTextChanged.pipe(
          debounceTime(this.searchQueryDueTime),
          distinctUntilChanged(),
          startWith(this.queryText),
        ),
      ]).subscribe(async query => {
        this.queryText = query[0];
        this.page = 0;
        if (this.queryText?.length > 0 || this.showDefaultData) {
          await this.fetchAndUpdateItems();
          this.queryChanged.next();
        }
      }),
      this.settingsProvider.settingsActionChanged$.subscribe(
        ({type, payload}) => {
          if (type === 'stapps.settings.changed') {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const {category, name, value} = payload!;
            this.logger.log(`received event "settings.changed" with category:
            ${category}, name: ${name}, value: ${JSON.stringify(value)}`);
          }
        },
      ),
      this.dataRoutingService.itemSelectListener().subscribe(async item => {
        if (this.itemRouting) {
          void this.router.navigate([
            'hebis-detail',
            (item.origin &&
              'originalId' in item.origin &&
              item.origin['originalId']) ||
              '',
          ]);
        }
      }),
    );
  }

  ngOnDestroy() {
    for (const subscription of this.subscriptions) {
      subscription.unsubscribe();
    }
  }
}
