#!/usr/bin/python

#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.


from sys import stdin, stdout
import hmac, hashlib
from datetime import datetime
import os
import urllib
from urllib2 import urlopen, HTTPError
from urlparse import urlparse, urljoin
import urllib
from optparse import OptionParser
from ConfigParser import ConfigParser

def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
    """
    Returns a bytestring version of 's', encoded as specified in 'encoding'.

    If strings_only is True, don't convert (some) non-string-like objects.

    This function was borrowed from Django
    """
    if strings_only and isinstance(s, (types.NoneType, int)):
        return s
    elif not isinstance(s, basestring):
        try:
            return str(s)
        except UnicodeEncodeError:
            if isinstance(s, Exception):
                # An Exception subclass containing non-ASCII data that doesn't
                # know how to print itself properly. We shouldn't raise a
                # further exception.
                return ' '.join([smart_str(arg, encoding, strings_only,
                        errors) for arg in s])
            return unicode(s).encode(encoding, errors)
    elif isinstance(s, unicode):
        r = s.encode(encoding, errors)
        return r
    elif s and encoding != 'utf-8':
        return s.decode('utf-8', errors).encode(encoding, errors)
    else:
        return s

def generate_smart_str(params):
    for (key, value) in params:
        yield smart_str(key), smart_str(value)

def urlencode(params):
    """
    A version of Python's urllib.urlencode() function that can operate on
    unicode strings. The parameters are first case to UTF-8 encoded strings and
    then encoded as per normal.
    """
    return urllib.urlencode([i for i in generate_smart_str(params)])


class Signer(object):

    def __init__(self, secret_key, api_key):
        self.secret_key = secret_key
        self.api_key = api_key

    def __call__(self, path, params):
        if self.api_key is None:
            return params
        params.append(('api_key', self.api_key))
        params.append(('api_timestamp', datetime.utcnow().isoformat()))
        message = path + '?' + urlencode(sorted(params))
        digest = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest()
        params.append(('api_signature', digest))
        return params

def main():
    usage = 'usage: %prog [options] [PageName [file]]'
    op = OptionParser(usage=usage)
    op.add_option('-c', '--config', metavar='CONFIG')
    op.add_option('-a', '--api-key', metavar='KEY')
    op.add_option('-s', '--secret-key', metavar='KEY')
    op.add_option('', '--anon', action='store_true')
    op.add_option('-u', '--url', metavar='URL')
    (options, args) = op.parse_args()

    pagename = None
    markdown = None
    method = 'GET'

    pagename_given = len(args) >= 1
    if pagename_given:
        pagename = args[0]

    filename_given = len(args) > 1
    if filename_given:
        method = 'PUT'
        f = open(args[1], 'r')
        markdown = f.read()

    config = ConfigParser()
    config.read([str(os.path.expanduser('~/.forge-api.ini')), str(options.config)])

    api_key = None
    secret_key = None
    if not options.anon:
        api_key = options.api_key or config.get('keys', 'api-key')
        secret_key = options.secret_key or config.get('keys', 'secret-key')

    url = options.url or config.get('wiki', 'url')
    if pagename_given:
        url = urljoin(url, urllib.quote(pagename))
    print url

    sign = Signer(secret_key, api_key)
    params = [('text', markdown)] if method=='PUT' else []
    params = sign(urlparse(url).path, params)
    try:
        if method=='PUT':
            result = urlopen(url, urlencode(params))
        else:
            result = urlopen(url+'?'+urlencode(params))
        stdout.write(result.read())
    except HTTPError, e:
        stdout.write(e.read())

if __name__ == '__main__':
    main()
