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());
    });
};
import { parse } from 'papaparse';
import { parseObject } from '../utils';
export class DatabaseDirectService {
    constructor(app) {
        this.app = app;
    }
    all(sheet, cacheTime = 0) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.app.Cache.getRefresh('database_' + sheet, cacheTime, () => __awaiter(this, void 0, void 0, function* () {
                // fetch csv file
                const csvText = yield this.app.Fetch.get(this.csvUrl(sheet), {}, { json: false });
                // parse
                const items = yield this.parseCSV(csvText);
                // process items
                for (let i = 0, l = items.length; i < l; i++) {
                    items[i]['_row'] = i + 2;
                    parseObject(items[i]);
                }
                return items;
            }));
        });
    }
    content(url, styles = 'clean', cacheTime = 0) {
        return __awaiter(this, void 0, void 0, function* () {
            const publishedId = url
                .replace('/pub', '')
                .split('/')
                .pop();
            const content = yield this.app.Cache.getRefresh('content_' + publishedId + '_' + styles, cacheTime, () => __awaiter(this, void 0, void 0, function* () {
                // fetch html content
                const html = yield this.app.Fetch.get(url + '?embedded=true', {}, { json: false });
                // parse
                return yield this.parseContent(html, styles);
            }));
            return { content };
        });
    }
    csvUrl(sheet) {
        const { databaseId, databaseGids } = this.app.options;
        return `https://docs.google.com/spreadsheets/d/`
            + databaseId +
            `/pub?gid=`
            + databaseGids[sheet] +
            `&single=true&output=csv`;
    }
    parseCSV(csv) {
        return new Promise((resolve, reject) => {
            parse(csv, {
                header: true,
                complete: (result) => !result.errors.length ? resolve(result.data) : reject(result.errors),
            });
        });
    }
    getContentClassStyles(html) {
        // copy class to inline
        const classGroups = {};
        const classes = {};
        // extract classes
        const classStrs = html.match(/class\=\"(.*?)\"/g);
        if (!!classStrs) {
            for (let i = 0, l = classStrs.length; i < l; i++) {
                const classStr = classStrs[i].match(/class\=\"(.*?)\"/);
                if (!!classStr) {
                    const classNamesStr = classStr.pop();
                    // add to classGroups
                    if (classNamesStr.indexOf(' ') > -1) {
                        classGroups[classNamesStr] = '';
                    }
                    // add to classes
                    const classNames = classNamesStr.split(' ').filter(Boolean);
                    for (let j = 0, lj = classNames.length; j < lj; j++) {
                        classes[classNames[j]] = '';
                    }
                }
            }
        }
        // get class styles
        for (const className of Object.keys(classes)) {
            const stylesMatch = html.match(new RegExp('.' + className + '{(.*?)}'));
            // extract styles
            if (!!stylesMatch) {
                classes[className] = stylesMatch.pop().replace(/\"/g, '\'') + ';';
            }
        }
        // get group styles
        for (const classGroup of Object.keys(classGroups)) {
            let groupStyles = '';
            const classNames = classGroup.split(' ').filter(Boolean);
            for (let i = 0, l = classNames.length; i < l; i++) {
                groupStyles = groupStyles + classes[classNames[i]];
            }
            // save styles to group
            classGroups[classGroup] = groupStyles;
        }
        return Object.assign({}, classGroups, classes);
    }
    parseContent(html, styles = 'clean') {
        let content = html; // original
        if (styles !== 'original') {
            // extract content, between: </head></html>
            content = html.match(/\<\/head\>(.*)\<\/html\>/).pop();
            // clean up
            content = content
                .replace(/\<body(.*?)\>/, '') // replace: <body...>
                .replace('</body>', '') // replace </body>
                .replace(/\<script(.*?)\<\/script\>/g, '') // remove all script tag
                .replace(/\<style(.*?)\<\/style\>/g, ''); // remove all style tag
            // replace redirect links
            const links = content.match(/\"https\:\/\/www\.google\.com\/url\?q\=(.*?)\"/g);
            if (!!links) {
                for (let i = 0, l = links.length; i < l; i++) {
                    const link = links[i];
                    const urlMatch = link.match(/\"https\:\/\/www\.google\.com\/url\?q\=(.*?)\&amp\;/);
                    if (!!urlMatch) {
                        const url = urlMatch.pop();
                        content = content.replace(link, '"' + url + '"');
                    }
                }
            }
            // styles
            if (styles === 'full') { // full
                // move class styles to inline
                const classStyles = this.getContentClassStyles(html);
                for (const key of Object.keys(classStyles)) {
                    content = content.replace(new RegExp('class="' + key + '"', 'g'), 'style="' + classStyles[key] + '"');
                }
                // TODO: move tag styles to inline
            }
            else { //clean
                // remove all attributes
                const removeAttrs = ['style', 'id', 'class', 'width', 'height'];
                for (let i = 0, l = removeAttrs.length; i < l; i++) {
                    content = content.replace(new RegExp('\ ' + removeAttrs[i] + '\=\"(.*?)\"', 'g'), '');
                }
            }
        }
        return content;
    }
}
