/*
 * Copyright (C) 2023 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, OnInit} from '@angular/core';
import {IonRefresher} from '@ionic/angular/standalone';
import {SCMessage, SCSearchFilter, SCSearchValueFilter, SCSetting} from '@openstapps/core';
import {NewsProvider} from '../news.provider';

/**
 * News page component
 */
@Component({
  selector: 'stapps-news-page',
  templateUrl: 'news-page.html',
  styleUrls: ['news-page.scss'],
})
export class NewsPageComponent implements OnInit {
  /**
   * Thing counter to start query the next page from
   */
  from = 0;

  /**
   * News (messages) to show
   */
  news: SCMessage[] = [];

  /**
   * Minimum page size of queries
   */
  minPageSize = 10;

  /**
   * Page size of queries
   */
  pageSize = 10;

  /**
   * Element size in px
   */
  elementSize = [300, 300];

  /**
   * Relevant settings
   */
  settings: SCSetting[];

  /**
   * Active filters
   */
  filters: SCSearchFilter[];

  constructor(private newsProvider: NewsProvider) {}

  /**
   * Fetch news from the backend
   */
  async fetchNews() {
    this.from = this.pageSize;
    this.news = await this.newsProvider.getList(this.pageSize, 0, [...this.filters]);
  }

  /**
   * Loads more news
   */
  async loadMore(infiniteScrollElement?: HTMLIonInfiniteScrollElement, more = this.pageSize): Promise<void> {
    const from = this.from;
    this.from += more;
    const fetchedNews = await this.newsProvider.getList(more, from, [...this.filters]);

    this.news = [...this.news, ...fetchedNews];
    await infiniteScrollElement?.complete();
  }

  calcPageSize(entry: ResizeObserverEntry) {
    this.pageSize = Math.max(
      this.minPageSize,
      Math.floor(entry.contentRect.width / this.elementSize[0]) *
        Math.ceil(entry.contentRect.height / this.elementSize[1] + 0.25),
    );
    if (!this.from || this.from === 0) return;
    const more = Math.max(0, this.pageSize - this.from);
    if (more !== 0) {
      void this.loadMore(undefined, Math.max(more, this.minPageSize));
    }
  }

  /**
   * Initialize the local variables on component initialization
   */
  async ngOnInit() {
    this.settings = await this.newsProvider.getCurrentSettings();
  }

  /**
   * Updates the shown list
   * @param refresher Refresher component that triggers the update
   */
  async refresh(refresher: IonRefresher) {
    try {
      await this.fetchNews();
    } catch {
      this.news = [];
    } finally {
      await refresher.complete();
    }
  }

  /**
   * Executed when filters have been changed
   * @param filters Current filters to be used
   */
  toggleFilter(filters: SCSearchValueFilter[]) {
    this.filters = filters;
    void this.fetchNews();
  }
}
