import Feed from '../../core/mixins/Feed.js';
import { InnertubeError } from '../../utils/Utils.js';
import HorizontalCardList from '../classes/HorizontalCardList.js';
import ItemSection from '../classes/ItemSection.js';
import SearchHeader from '../classes/SearchHeader.js';
import SearchRefinementCard from '../classes/SearchRefinementCard.js';
import SearchSubMenu from '../classes/SearchSubMenu.js';
import SectionList from '../classes/SectionList.js';
import UniversalWatchCard from '../classes/UniversalWatchCard.js';
import { observe } from '../helpers.js';
import { ReloadContinuationItemsCommand } from '../index.js';
import AppendContinuationItemsAction from '../classes/actions/AppendContinuationItemsAction.js';
export default class Search extends Feed {
    header;
    results;
    refinements;
    estimated_results;
    sub_menu;
    watch_card;
    refinement_cards;
    constructor(actions, data, already_parsed = false) {
        super(actions, data, already_parsed);
        const contents = this.page.contents_memo?.getType(SectionList)[0].contents ||
            this.page.on_response_received_commands?.[0].as(AppendContinuationItemsAction, ReloadContinuationItemsCommand).contents;
        if (!contents)
            throw new InnertubeError('No contents found in search response');
        if (this.page.header)
            this.header = this.page.header.item().as(SearchHeader);
        this.results = observe(contents.filterType(ItemSection).flatMap((section) => section.contents));
        this.refinements = this.page.refinements || [];
        this.estimated_results = this.page.estimated_results || 0;
        if (this.page.contents_memo) {
            this.sub_menu = this.page.contents_memo.getType(SearchSubMenu)[0];
            this.watch_card = this.page.contents_memo.getType(UniversalWatchCard)[0];
        }
        this.refinement_cards = this.results?.firstOfType(HorizontalCardList);
    }
    /**
     * Applies given refinement card and returns a new {@link Search} object. Use {@link refinement_card_queries} to get a list of available refinement cards.
     */
    async selectRefinementCard(card) {
        let target_card;
        if (typeof card === 'string') {
            if (!this.refinement_cards)
                throw new InnertubeError('No refinement cards found.');
            target_card = this.refinement_cards?.cards.find((refinement_card) => {
                return refinement_card.is(SearchRefinementCard) && refinement_card.query === card;
            });
            if (!target_card)
                throw new InnertubeError(`Refinement card "${card}" not found`, { available_cards: this.refinement_card_queries });
        }
        else if (card.type === 'SearchRefinementCard') {
            target_card = card;
        }
        else {
            throw new InnertubeError('Invalid refinement card!');
        }
        const page = await target_card.endpoint.call(this.actions, { parse: true });
        return new Search(this.actions, page, true);
    }
    /**
     * Returns a list of refinement card queries.
     */
    get refinement_card_queries() {
        return this.refinement_cards?.cards.as(SearchRefinementCard).map((card) => card.query) || [];
    }
    /**
     * Retrieves next batch of search results.
     */
    async getContinuation() {
        const response = await this.getContinuationData();
        if (!response)
            throw new InnertubeError('Could not get continuation data');
        return new Search(this.actions, response, true);
    }
}
//# sourceMappingURL=Search.js.map