/*
 * Copyright (c) 2011 Red Hat, Inc.
 *
 * Polari 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; either version 2 of the License, or (at your
 * option) any later version.
 *
 * Polari 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 Polari; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Authors: Cosimo Cecchi <cosimoc@redhat.com>
 *          Florian Müllner <fmuellner@gnome.org>
 *
 */

const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Soup = imports.gi.Soup;

const Signals = imports.signals;

const FPASTE_BASEURL = 'http://paste.fedoraproject.org/'

// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';

const _urlRegexp = new RegExp(
    '(^|' + _leadingJunk + ')' +
    '(' +
        '(?:' +
            '(?:http|https|ftp)://' +             // scheme://
            '|' +
            'www\\d{0,3}[.]' +                    // www.
            '|' +
            '[a-z0-9.\\-]+[.][a-z]{2,4}/' +       // foo.xx/
        ')' +
        '(?:' +                                   // one or more:
            '[^\\s()<>]+' +                       // run of non-space non-()
            '|' +                                 // or
            _balancedParens +                     // balanced parens
        ')+' +
        '(?:' +                                   // end with:
            _balancedParens +                     // balanced parens
            '|' +                                 // or
            _notTrailingJunk +                    // last non-junk char
        ')' +
    ')', 'gi');


let debugInit = false;
let debugEnabled = false;

function debug(str) {
    if (!debugInit) {
        let env = GLib.getenv('POLARI_DEBUG');
        if (env)
            debugEnabled = true;

        debugInit = true;
    }

    if (debugEnabled)
        log('DEBUG: ' + str);
}

function addJSSignalMethods(proto) {
    proto.connectJS = Signals._connect;
    proto.disconnectJS = Signals._disconnect;
    proto.emitJS = Signals._emit;
    proto.disconnectAllJS = Signals._disconnectAll;
}

// findUrls:
// @str: string to find URLs in
//
// Searches @str for URLs and returns an array of objects with %url
// properties showing the matched URL string, and %pos properties indicating
// the position within @str where the URL was found.
//
// Return value: the list of match objects, as described above
function findUrls(str) {
    let res = [], match;
    while ((match = _urlRegexp.exec(str)))
        res.push({ url: match[2], pos: match.index + match[1].length });
    return res;
}

function fpaste(text, user, callback) {
    let getUrl = function(session, id) {
        let longUrl = FPASTE_BASEURL + id;
        session.queue_message(Soup.Message.new('POST', longUrl + '/json'),
            function(session, message) {
                if (message.status_code != Soup.KnownStatusCode.OK) {
                    callback(null);
                    return;
                }

                // workaround: the response contains the pasted data
                // unescaped (e.g. newlines), which is not legal json;
                // just grab the property we're interested in
                let lines = message.response_body.data.split('\n');
                let shortUrl = null;
                for (let i = 0; i < lines.length; i++) {
                    if (lines[i].indexOf('short_url') > -1) {
                        shortUrl = lines[i];
                        break;
                    }
                }

                let info = {};
                try {
                    if (shortUrl)
                        info = JSON.parse('{ %s }'.format(shortUrl));
                } catch(e) {
                    log(e.message);
                }
                if (info.short_url)
                    callback(info.short_url);
                else
                    callback(longUrl);
            });
    };
    let params = {
        paste_data: text,
        paste_lang: 'text',
        paste_user: user,
        api_submit: '1',
        mode: 'json'
    };

    let session = new Soup.Session();
    let message = Soup.form_request_new_from_hash('POST', FPASTE_BASEURL, params);
    session.queue_message(message,
        function(session, message) {
            if (message.status_code != Soup.KnownStatusCode.OK) {
                callback(null);
                return;
            }

            let info = {};
            try {
                info = JSON.parse(message.response_body.data);
            } catch(e) {
                log(e.message);
            }
            if (info.result && info.result.id)
                getUrl(session, info.result.id);
            else
                callback(null);
        });
}
