"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const Indexer_1 = require("./Indexer");
const node_fetch_1 = require("node-fetch");
const qs = require("querystring");
const storyboard_1 = require("storyboard");
const defaultOptions = {
    hostname: 'redacted.ch',
    username: '',
    protocol: 'https',
    port: 443,
    tracker: '',
    endpoint: 'ajax.php',
    rateLimits: {
        frame: 10 * 1000,
        calls: 5
    }
};
class GazelleIndexer extends Indexer_1.Indexer {
    constructor(config) {
        super(Object.assign({}, defaultOptions, config));
        this.sessionCookie = '';
    }
    logout() {
        this.sessionCookie = '';
        this.signedIn = false;
        return Promise.resolve();
    }
    login(password) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.signedIn) {
                return Promise.resolve();
            }
            else {
                storyboard_1.mainStory.info('cascade', `Trying to logging you in as ${this.username}...`);
                let url = `${this.protocol}://${this.hostname}:${this.port}/login.php`;
                const time = Date.now();
                const res = yield node_fetch_1.default(url, {
                    method: 'POST',
                    redirect: 'manual',
                    body: qs.stringify({
                        username: this.username,
                        password: password,
                        keeplogged: 1
                    }),
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    }
                });
                storyboard_1.mainStory.debug('cascade', `POST ${url} - ${time - Date.now()} ms`, {
                    attach: res.timeout,
                    attachLevel: 'trace'
                });
                if (res.status === 302) {
                    const setCookie = res.headers.get('Set-Cookie');
                    const cookie = setCookie.split(';').map(st => st.trim().split('=')).reduce((acc, val) => {
                        return Object.assign({}, acc, {
                            [val[0]]: val[1] || true
                        });
                    }, {});
                    this.sessionCookie = cookie.session;
                    this.signedIn = true;
                    return;
                }
                throw new Error('Wrong username or password');
            }
        });
    }
    call(method, args, endpoint = this.endpoint) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.signedIn)
                throw new Error('Please login before using API');
            yield this.limit();
            const query = qs.stringify(Object.assign({}, {
                action: method
            }, args));
            const url = `${this.protocol}://${this.hostname}:${this.port}/${this.endpoint}?${query}`;
            const time = Date.now();
            const res = yield node_fetch_1.default(url, {
                headers: {
                    'Cookie': `session=${this.sessionCookie}`
                }
            });
            storyboard_1.mainStory.info('cascade', `GET ${url} - ${res.status} - ${time - Date.now()} ms`, {
                attach: res,
                attachLevel: 'trace'
            });
            return yield res.json();
        });
    }
    searchAlbum(album) {
        return __awaiter(this, void 0, void 0, function* () {
            const res = yield this.call('browse', {
                searchstr: '',
                artistname: album.artist,
                groupname: album.name
            });
            const { results } = res.response;
            return results.reduce((acc, group) => {
                const torrents = group.torrents.map((t) => {
                    return {
                        torrent_id: '' + t.torrentId,
                        tracker: this.tracker,
                        seeders: t.seeders,
                        leechers: t.leechers,
                        score: t.seeders * t.seeders / (t.leechers + 1),
                        format: t.format.toLowerCase(),
                        bitrate: 0,
                        _id: '',
                        wanted: '',
                        name: `${group.artist} - ${group.groupName} - ${group.groupYear} (${t.media} - ${t.format} ${t.encoding})`
                    };
                });
                return [].concat(acc, ...torrents);
            }, []);
        });
    }
    downloadRelease(torrent_id) {
        return __awaiter(this, void 0, void 0, function* () {
            const query = qs.stringify({
                id: torrent_id,
                action: 'download'
            });
            const url = `${this.protocol}://${this.hostname}:${this.port}/torrents.php?${query}`;
            const time = Date.now();
            const res = yield node_fetch_1.default(url, {
                headers: {
                    'Cookie': `session=${this.sessionCookie}`
                }
            });
            storyboard_1.mainStory.info('cascade', `GET ${url} - ${res.status} - ${time - Date.now()} ms`, {
                attach: res,
                attachLevel: 'trace'
            });
            if (res.headers.get('content-type') === 'text/html; charset=UTF-8')
                throw new Error('Torrent doesnt exist');
            return yield res.buffer();
        });
    }
}
exports.GazelleIndexer = GazelleIndexer;
//# sourceMappingURL=GazelleIndexer.js.map