#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Pownce API Service Implements
"""
import os
import sys
import sha
import random
import time
import md5
import base64
import string
import urllib
import httplib
import datetime
import mimetypes
import feedparser
from email.MIMEBase import MIMEBase
from email import Encoders
from xml.dom import minidom

__author__ = 'mattn <mattn.jp@gmail.com>'
__url__ = 'http://www.ac.cyberhome.ne.jp/~mattn/'
__date__ = 'Tue, 31 Jul 2007'
__version__ = "0.01"
__credits__ = """Yasuhiro Matsumoto, main developer"""

class Message:
    def __init__(self, message):
        self.message = message

    def data(self, to, auth):
        content_type = "application/x-www-form-urlencoded; charset=utf-8"
        body = "auth=%s&note_to=%s&note_body=%s&note_type=%s" % (
                urllib.quote(auth),
                urllib.quote(to),
                urllib.quote(self.message),
                "note-message")
        return content_type, body

class Link:
    def __init__(self, message, link):
        self.message = message
        self.link = link

    def data(self, to, auth):
        content_type = "application/x-www-form-urlencoded; charset=utf-8"
        body = "auth=%s&note_to=%s&note_body=%s&note_type=%s&url=%s" % (
                urllib.quote(auth),
                urllib.quote(to),
                urllib.quote(self.message),
                "note-link",
                urllib.quote(self.link))
        return content_type, body

class File(Message):
    def __init__(self, message, file):
        self.message = message
        self.file = file

    def data(self, to, auth):
        boundary = "------------ae0GI3ei4gL6ae0Ij5Ij5ei4KM7ei4"
        ctype = mimetypes.guess_type(self.file)[0]
        if ctype is None:
            ctype = 'application/octet-stream'
        ctype = 'text/plain'
        mtype, stype = ctype.split('/', 1)
        mime = MIMEBase(mtype, stype)
        mime.set_payload(open(self.file, 'rb').read())
        Encoders.encode_base64(mime)

        lines = []
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"auth\"")
        lines.append("")
        lines.append(auth)
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"note_body\"")
        lines.append("")
        lines.append("test")
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"note_to\"")
        lines.append("")
        lines.append(to)
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"note_type\"")
        lines.append("")
        lines.append("note-file")
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"media_file\"; filename=\"%s\"" % os.path.basename(self.file))
        #lines.append("Content-Transfer-Encoding: base64")
        #lines.append("Content-Type: " + ctype)
        #lines.append("")
        #lines.append(mime.get_payload())
        lines.append("Content-Type: " + ctype)
        lines.append("")
        lines.append(open(self.file, 'rb').read())
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"Filename\"")
        lines.append("")
        lines.append(os.path.basename(self.file))
        lines.append("--" + boundary)
        lines.append("Content-Disposition: form-data; name=\"Upload\"")
        lines.append("")
        lines.append("Submit Query")
        lines.append('--' + boundary + '--')
        content_type = "multipart/form-data; boundary=%s" % boundary
        body = "\r\n".join(lines)
        return content_type, body

class Event(Message):
    def __init__(self, message, location='', name='', datetime=None):
        self.message = message
        self.location = location
        self.name = name
        if datetime is None:
            self.datetime = time.localtime()
        else:
            self.datetime = datetime

    def data(self, to, auth):
        content_type = "application/x-www-form-urlencoded; charset=utf-8"
        dtime = time.strftime('%I:%M %p', self.datetime)
        body = "auth=%s&note_to=%s&note_body=%s&note_type=%s&event_name=%s&event_location=%s&event_time=%s&event_date_year=%s&event_date_month=%s&event_date_day=%s" % (
                urllib.quote(auth),
                urllib.quote(to),
                urllib.quote(self.message),
                "note-event",
                urllib.quote(self.name),
                urllib.quote(self.location),
                urllib.quote(dtime),
                self.datetime[0],
                self.datetime[1],
                self.datetime[2])
        return content_type, body


class Session:
    """
    initialize service variables.
    """
    def __init__(self, userid, passwd):
        self.userid = userid
        self.passwd = passwd
        self.useragent = 'PownceAPI.py'
        self.cookie = None
        self.token = self.get_token()

    def get_token(self):
        headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
                "Authorization": "Basic " + base64.encodestring("%s:%s" % (self.userid, self.passwd))}
        conn = httplib.HTTPConnection("pownce.com")
        conn.request('POST', '/api/login/', body='', headers=headers)
        response = conn.getresponse()
        data = response.read()
        doc = minidom.parseString(data)
        node = doc.getElementsByTagName('login')[0]
        self.cookie = response.getheader("Set-Cookie").split(';')[0]
        return node.getAttribute('token')

    def get_nonce(self):
        return md5.md5('%s:%s' % (time.ctime(), ["0123456789"[random.randrange(0, 9)] for i in range(20)])).hexdigest()[:16]

    def get_auth_header(self):
        nonce = self.get_nonce()
        post_creation_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
        password_digest = base64.b64encode(sha.new(nonce + post_creation_time + self.token).digest())
        authorization_header = 'UsernameToken Username="%s", PasswordDigest="%s", Created="%s", Nonce="%s"' \
            % (self.userid, password_digest, post_creation_time, nonce)
        return authorization_header

    def get_headers(self):
        headers = {'User-Agent': self.useragent}
        return headers

    def send_item(self, to, item):
        content_type, body = item.data(to, self.get_auth_header())
        headers = self.get_headers()
        headers["Content-Type"] = content_type
        headers["Content-Length"] = len(body)
        headers["Cookie"] = self.cookie
        conn = httplib.HTTPConnection("pownce.com")
        conn.request('POST', '/api/notes/', body=body, headers=headers)
        response = conn.getresponse()
        data = response.read()
        if response.status != 200:
          raise Exception(response.status, response.reason)

    def get_notes(self):
        headers = self.get_headers()
        conn = httplib.HTTPConnection("pownce.com")
        body = "auth=%s" % (urllib.quote(self.get_auth_header()))
        conn.request('POST', '/api/notes/for/%s/' % self.userid, body=body, headers=headers)
        response = conn.getresponse()
        data = response.read()
        return feedparser.parse(data)

