/*
 * 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 {Injectable} from '@angular/core';
import {
  SCBooleanFilterArguments,
  SCMessage,
  SCSearchBooleanFilter,
  SCSearchFilter,
  SCSearchQuery,
  SCSearchValueFilter,
  SCSetting,
} from '@openstapps/core';
import {DataProvider} from '../data/data.provider';
import {
  newsFilterSettingsCategory,
  newsFilterSettingsFieldsMapping,
  NewsFilterSettingsNames,
} from './news-filter-settings';
import {SettingsProvider} from '../settings/settings.provider';

/**
 * Service for providing news messages
 */
@Injectable({
  providedIn: 'root',
})
export class NewsProvider {
  constructor(
    private dataProvider: DataProvider,
    private settingsProvider: SettingsProvider,
  ) {}

  async getCurrentSettings(): Promise<SCSetting[]> {
    const settings: SCSetting[] = [];
    for (const settingName of Object.keys(newsFilterSettingsFieldsMapping) as NewsFilterSettingsNames[]) {
      settings.push(await this.settingsProvider.getSetting(newsFilterSettingsCategory, settingName));
    }
    return settings;
  }

  async getCurrentFilters(): Promise<SCSearchFilter[]> {
    const settings = await this.getCurrentSettings();
    const filtersMap = new Map<NewsFilterSettingsNames, SCSearchValueFilter>();
    for (const setting of settings) {
      filtersMap.set(
        setting.name as NewsFilterSettingsNames,
        DataProvider.createValueFilter(
          newsFilterSettingsFieldsMapping[setting.name as NewsFilterSettingsNames],
          setting.value as string,
        ),
      );
    }

    return [...filtersMap.values()];
  }

  /**
   * Get news messages
   * @param size How many messages/news to fetch
   * @param from From which (results) page to start
   * @param filters Additional filters to apply
   */
  async getList(size: number, from: number, filters?: SCSearchFilter[]): Promise<SCMessage[]> {
    const query: SCSearchQuery = {
      filter: {
        type: 'boolean',
        arguments: {
          filters: [
            {
              type: 'value',
              arguments: {
                field: 'type',
                value: 'message',
              },
            },
          ],
          operation: 'and',
        },
      },
      sort: [
        {
          type: 'generic',
          arguments: {
            field: 'datePublished',
          },
          order: 'desc',
        },
      ],
      size: size,
      from: from,
    };

    if (filters !== undefined) {
      for (const filter of filters) {
        ((query.filter as SCSearchBooleanFilter).arguments as SCBooleanFilterArguments).filters.push(filter);
      }
    }

    const result = await this.dataProvider.search(query);

    return result.data as SCMessage[];
  }
}
