/*
 * Copyright 2015 Canonical Ltd.
 *
 * This file is part of webapps-core.
 *
 * webapps-core 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; version 3.
 *
 * unity-webapps-qml 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var request_url = {
    scheme: 'https://',
    host: 'upload.twitter.com',
    path: '/1.1/media/upload.json'
};

var api = external.getUnityObject('1.0');
var hub = api.ContentHub;
var activeTransfer = null;

function _shareRequested(transfer) {
    if (activeTransfer) {
        console.log('Error, trying' +
                    ' to launch the share' +
                    ' UI while a transfer is' +
                    ' already occuring');
        return;
    }
    activeTransfer = transfer;

    // Make sure that we have the proper
    transfer.contentType(function(type) {
        if (type === hub.ContentType.Pictures) {
            transfer.items(function(items) {
	        api.launchEmbeddedUI(
                    "HubSharer",
                    uploadPhoto,
                    {"fileToShare": items[0]});
            });
        } else if (type === hub.ContentType.Links) {
            transfer.items(function(items) {
                uploadLink(items[0].url)
            });
        }
    });
};
hub.onShareRequested(_shareRequested);


function uploadLink(url) {
    window.location.href = 'https://www.twitter.com/share?url=' + url
    if (activeTransfer) {
        activeTransfer.setState(
            hub.ContentTransfer.State.Finalized)
        activeTransfer = null
    }
}

function generateNonce() {
    // base64 encoding 32 bytes of random data, and stripping out all non-word
    // characters
    var nonce = ''
    for (var i = 0; i < 32; ++i) {
        var pick = Math.floor(Math.random() * 72) + 48
        if (pick >= 58 && pick <= 64) {
            pick = Math.floor(Math.random() * 9) + 48
        } else if (pick >= 91 && pick <= 96) {
            pick = Math.floor(Math.random() * 25) + 65
        }
        nonce += String.fromCharCode(pick);
    }
    return nonce
}

function getTimestamp() {
    return String(Math.round((new Date()).getTime() / 1000.0))
}

function getSigningKey(consumer_secret, oauth_secret) {
    return encodeURIComponent(consumer_secret) +
	'&' + encodeURIComponent(oauth_secret);
}

function encodeWwwFormUrlEncoded(parameters) {
    var encoded = ''
    if (parameters) {
	for (var p in parameters) {
	    if (parameters.hasOwnProperty(p)) {
		if (encoded.length !== 0) {
		    encoded += "&";
		}
		encoded += encodeURIComponent(p) +
		    '=' + encodeURIComponent(parameters[p]);
	    }
	}
    }
    return encoded
}

// from https://dev.twitter.com/oauth/overview/creating-signatures
function createSignature(
    uri,
    oauth_consumer_key,
    oauth_consumer_key_secret,
    oauth_nonce,
    oauth_signature_method,
    oauth_timestamp,
    oauth_token,
    oauth_token_secret,
    oauth_version,
    parameters,
    callback) {

    var signature_parameters = {
        'oauth_consumer_key' : encodeURIComponent(oauth_consumer_key),
        'oauth_nonce' : encodeURIComponent(oauth_nonce),
        'oauth_signature_method' : encodeURIComponent(oauth_signature_method),
        'oauth_timestamp' : encodeURIComponent(oauth_timestamp),
        'oauth_token' : encodeURIComponent(oauth_token),
        'oauth_version' : encodeURIComponent(oauth_version)
    };
    if (parameters) {
        for (var p in parameters) {
            if (parameters.hasOwnProperty(p)) {
                signature_parameters[p] =
                    encodeURIComponent(parameters[p]);
            }
        }
    }

    var keys = [];
    for (var sp in signature_parameters) {
        if (signature_parameters.hasOwnProperty(sp)) {
            keys.push(sp);
        }
    }
    keys.sort();

    var content = '';
    for (var i in keys) {
        if (keys.hasOwnProperty(i)) {
            if (content.length !== 0) {
		content += '&';
            }
            content += encodeURIComponent(keys[i]) +
		'=' + signature_parameters[keys[i]];
	}
    }

    // from https://dev.twitter.com/rest/public/uploading-media
    // "POST or query string parameters are not used when calculating
    //  an OAuth signature basestring or signature. Only the oauth_*
    //  parameters are used"

    var signature_base_string = 
	'POST&' +
        encodeURIComponent(uri) +
        '&' + encodeURIComponent(content);

    return api.ToolsApi.getHmacHash(
        signature_base_string,
        api.ToolsApi.CryptographicAlgorithm.SHA1,
        getSigningKey(oauth_consumer_key_secret, oauth_token_secret),
        callback);
}

function formatOAuthHttpHeader(
        uri,
        oauth_consumer_key,
        oauth_consumer_key_secret,
        oauth_nonce,
        oauth_timestamp,
        oauth_token,
        oauth_token_secret,
        parameters,
        callback) {
    var oauth_version = '1.0';
    var oauth_signature_method = 'HMAC-SHA1';
    createSignature(
        uri,
        oauth_consumer_key,
        oauth_consumer_key_secret,
        oauth_nonce,
        oauth_signature_method,
        oauth_timestamp,
        oauth_token,
        oauth_token_secret,
        oauth_version,
	parameters,
        function(signature) {
            if (signature.errorMsg
                && signature.errorMsg.length !== 0) {
                callback({errorMessage: signature.errorMsg})
                return;
            }

            var sep = ', ';
            var auth_header_content = 'OAuth ';

            auth_header_content += 'oauth_consumer_key="' + oauth_consumer_key + '"';
            auth_header_content += sep + 'oauth_nonce="' + oauth_nonce + '"';
            auth_header_content += sep + 'oauth_signature_method="' + oauth_signature_method + '"';
            auth_header_content += sep + 'oauth_timestamp="' + oauth_timestamp  + '"';
            auth_header_content += sep + 'oauth_token="' + oauth_token + '"';
            auth_header_content += sep + 'oauth_version="' + oauth_version + '"';
            auth_header_content += sep + 'oauth_signature="' + encodeURIComponent(signature.result) + '"';
            
            callback({errorMessage: '', result: auth_header_content});
        });
}

function doSendUploadRequest(
        uri,
        upload_request_content,
        parameters,
        authorization_header,
        onResourceUploadedCallback) {

    // TODO GET help/configuration, 'photo_size_limit' / 'max_media_per_upload'

    api.ToolsApi.__private__.sendHttpRequest(
        uri,
        {
            headers: {
                'Authorization': authorization_header,
		'Content-Type': 'application/x-www-form-urlencoded'
            }
        },
        encodeWwwFormUrlEncoded(parameters),
        function(results) {
            if (activeTransfer) {
                activeTransfer.setState(
                    hub.ContentTransfer.State.Finalized);
            }

            if ( ! results.success) {
		activeTransfer = null;
		onResourceUploadedCallback(
                    false,
                    {errorMessage: results.errorMsg});
		return;
            }

	    var update_parameters = {
		status: upload_request_content.message,
		media_ids: JSON.parse(results.response).media_id_string
	    };

            formatOAuthHttpHeader( 
		"https://api.twitter.com/1.1/statuses/update.json",
		upload_request_content.consumerKey,
		upload_request_content.consumerSecretKey,
		generateNonce(),
		getTimestamp(),
		upload_request_content.accessToken,
		upload_request_content.accessTokenSecret,
		update_parameters,
		function(content) {
		    api.ToolsApi.__private__.sendHttpRequest(
			"https://api.twitter.com/1.1/statuses/update.json",
			{
			    headers: {
				'Authorization': content.result,
				'Content-Type': 'application/x-www-form-urlencoded'
			    }
			},
			encodeWwwFormUrlEncoded(update_parameters),
			function(results) {
		            activeTransfer = null;
			    window.location.reload();
			    onResourceUploadedCallback(
                                results.success,
                                {errorMessage: results.errorMsg});
			});
		}
	    );
        }
    )
}

function uploadPhoto(res, onResourceUploadedCallback) {
    try {
        var results = JSON.parse(res);
        if (results.status == "cancelled") {
            activeTransfer.setState(
                hub.ContentTransfer.State.Aborted);
        }
	var payload = results.fileToShare.split(',')[1];
	var parameters = {
	    media: payload
	};
	var uri = request_url.scheme + request_url.host + request_url.path
        formatOAuthHttpHeader( 
	    uri,
            results.consumerKey,
            results.consumerSecretKey,
            generateNonce(),
            getTimestamp(),
            results.accessToken,
            results.accessTokenSecret,
	    parameters,
            function(content) {
                if (content.errorMsg
                    && content.errorMsg.length !== 0) {
                    onResourceUploadedCallback(
                        false, {errorMessage: content.errorMsg})
		    activeTransfer = null;
                    return;
                }

                doSendUploadRequest(
		    uri,
		    results,
		    parameters,
                    content.result,
                    onResourceUploadedCallback)
            });

    } catch (e) {
        console.log('Exception while transferring: ' + e.toString());
    }
}
