import { api } from './util.js';
const processors = {
    extracts: data => {
        return { extract: data.extract };
    },
    links: data => {
        return { links: data.links.map(e => e.title) };
    },
    extlinks: data => {
        return { extlinks: data.extlinks.map(e => e['*']) };
    },
    langlinks: data => {
        return {
            langlinks: data.langlinks.map(link => {
                return {
                    lang: link.lang,
                    title: link['*'],
                    url: link.url
                };
            })
        };
    },
    coordinates: data => {
        if (data.coordinates) {
            return { coordinates: data.coordinates[0] };
        }
        else {
            return {};
        }
    },
    categories: data => {
        return { categories: data.categories.map(e => e.title) };
    },
    pageimages: data => {
        return {
            image: {
                name: data.pageimage,
                thumbnail: data.thumbnail,
                original: data.original
            }
        };
    }
};
function process(props, rawPageData) {
    const data = { title: rawPageData.title };
    return props.reduce((memo, prop) => {
        if (processors[prop])
            Object.assign(memo, processors[prop](rawPageData));
        return memo;
    }, data);
}
/**
 * Chain API requests together
 * @example
 * // Get page summary and images in same request
 * wiki.page('batman').then(page => page.chain().summary().image().request()).then(console.log);
 * @namespace QueryChain
 */
export default class QueryChain {
    constructor(apiOptions, id) {
        this.id = id;
        this.apiOptions = apiOptions;
        this._params = { pageids: id };
        this.props = new Set();
    }
    params() {
        const prop = [...this.props].join('|');
        return Object.assign({}, this._params, { prop });
    }
    direct(key, ...args) {
        return this[key](...args)
            .request()
            .then(res => res[key]);
    }
    // TODO: Add page searches for root calls - generators
    // TODO: Add pagination helper method
    /**
     * Make combined API request
     * @method QueryChain#request
     * @returns {Object|Array} - Data object(s) depending on where the chain was created from
     */
    request() {
        const props = [...this.props];
        return api(this.apiOptions, this.params())
            .then(res => {
            if (this.id) {
                return res.query.pages[this.id];
            }
            else {
                return Object.values(res.query.pages);
            }
        })
            .then(data => {
            if (Array.isArray(data)) {
                return data.map(e => process(props, e));
            }
            else {
                return process(props, data);
            }
        });
    }
    chain(prop, params = {}) {
        if (prop) {
            this.props.add(prop);
        }
        Object.assign(this._params, params);
        return this;
    }
    /**
     * @summary Finds pages near a specific point
     * @method QueryChain#geosearch
     * @returns {QueryChain}
     */
    geosearch(latitude, longitude, radius) {
        return this.chain(undefined, {
            generator: 'geosearch',
            ggsradius: radius,
            ggscoord: `${latitude}|${longitude}`
        });
    }
    search(query, limit = 50) {
        return this.chain(undefined, {
            list: 'search',
            srsearch: query,
            srlimit: limit
        });
    }
    /**
     * @summary Useful for extracting structured section content
     * @method QueryChain#content
     * @returns {QueryChain}
     */
    content() {
        return this.chain('extracts', {
            explaintext: '1'
        });
    }
    /**
     * @summary Useful for extracting summary content
     * @method QueryChain#summary
     * @returns {QueryChain}
     */
    summary() {
        return this.chain('extracts', {
            explaintext: '1',
            exintro: '1'
        });
    }
    /**
     * @summary Extract image
     * @method QueryChain#image
     * @returns {QueryChain}
     */
    image(types = { thumbnail: true, original: false, name: true }) {
        return this.chain('pageimages', {
            piprop: Object.keys(types)
                .filter(k => types[k])
                .join('|')
        });
    }
    /**
     * @summary Extract external links
     * @method QueryChain#extlinks
     * @returns {QueryChain}
     */
    extlinks() {
        return this.chain('extlinks', {
            ellimit: 'max'
        });
    }
    /**
     * @summary Extract page links
     * @method QueryChain#links
     * @returns {QueryChain}
     */
    links(limit = 100) {
        return this.chain('links', {
            plnamespace: 0,
            pllimit: limit
        });
    }
    /**
     * @summary Extract categories
     * @method QueryChain#categories
     * @returns {QueryChain}
     */
    categories(limit = 100) {
        return this.chain('categories', {
            pllimit: limit
        });
    }
    /**
     * @summary Extract coordinates
     * @method QueryChain#coordinates
     * @returns {QueryChain}
     */
    coordinates() {
        return this.chain('coordinates');
    }
    /**
     * @summary Get list of links to different translations
     * @method QueryChain#langlinks
     * @returns {QueryChain}
     */
    langlinks() {
        return this.chain('langlinks', {
            lllimit: 'max',
            llprop: 'url'
        });
    }
}
