#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Mixi API Service Implements
"""
import os
import sys
import sha
import random
import time
import base64
import urllib
import httplib
from xml.dom import minidom

__author__ = 'mattn <mattn.jp@gmail.com>'
__url__ = 'http://mattn.kaoriya.net/'
__date__ = 'Mon, 09 Jul 2007'
__version__ = "0.03"
__credits__ = """Yasuhiro Matsumoto, main developer"""

"""
Mixi API Service Implementation class
"""
class Service:
    """
    initialize service variables.
    """
    def __init__(self, userid, passwd):
        self.userid = userid
        self.passwd = passwd
        self.useragent = 'MixiAPI.py'

    """
    get nonce for server.
    """
    def get_nonce(self):
        private = str(random.random())
        timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
        return '%s %s' % (timestamp, sha.new('%s:%s' % (timestamp, private)).hexdigest())

    """
    build post header.
    """
    def get_headers(self):
        nonce = self.get_nonce()
        base64_encoded_nonce = base64.encodestring(nonce).replace('\n', '')
        post_creation_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
        password_digest = base64.encodestring(sha.new(nonce + post_creation_time + self.passwd).digest()).replace('\n', '')
        authorization_header = 'UsernameToken Username="%s", PasswordDigest="%s", Created="%s", Nonce="%s"' \
            % (self.userid, password_digest, post_creation_time, base64_encoded_nonce)

        headers = {'Content-Type': 'application/atom+xml', 
        'X-WSSE': authorization_header, 
        'Authorization': 'WSSE profile="UsernameToken"',
        'User-Agent': self.useragent}
        return headers

    """
    query root end point of entry server.
    """
    def get_footstamps(self):

        footstamps = []
        typeinfo = urllib.splittype("http://mixi.jp/atom/tracks")
        hostinfo = urllib.splithost(typeinfo[1])
        conn = httplib.HTTPConnection(hostinfo[0])
        conn.request('GET', hostinfo[1], body='', headers=self.get_headers())
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("can't login")
        data = response.read()
        conn.close()
        doc = minidom.parseString(data)
        node = doc.getElementsByTagName('workspace')[0]
        node = node.getElementsByTagName('collection')[0]
        service = node.getAttribute('href')

        conn.request('GET', service, body='', headers=self.get_headers())
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("can't login")
        data = response.read()
        conn.close()
        doc = minidom.parseString(data)
        feed = doc.getElementsByTagName('feed')[0]
        entries = feed.getElementsByTagName('entry')
        for entry in entries:
            author = entry.getElementsByTagName('author')[0]
            footstamp = {
                'id': entry.getElementsByTagName('id')[0].childNodes[0].data,
                'link': entry.getElementsByTagName('link')[0].getAttribute('href'),
                'title': entry.getElementsByTagName('title')[0].childNodes[0].data,
                'updated': entry.getElementsByTagName('updated')[0].childNodes[0].data,
                'author': {
                    'name': author.getElementsByTagName('name')[0].childNodes[0].data,
                    'tracks:image': author.getElementsByTagName('tracks:image')[0].childNodes[0].data,
                    'tracks:relation': author.getElementsByTagName('tracks:relation')[0].childNodes[0].data
                }
            }
            footstamps.append(footstamp)
        return footstamps

    """
    get album infos.
    """
    def get_albums(self, name = ''):
        albums = []
        typeinfo = urllib.splittype("http://photo.mixi.jp/atom")
        hostinfo = urllib.splithost(typeinfo[1])
        conn = httplib.HTTPConnection(hostinfo[0])
        conn.request('GET', hostinfo[1], body='', headers=self.get_headers())
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("can't login")
        data = response.read()
        conn.close()

        doc = minidom.parseString(data)
        node = doc.getElementsByTagName('workspace')[0]
        node = node.getElementsByTagName('collection')[0]
        service = node.getAttribute('href')

        conn.request('GET', service, body='', headers=self.get_headers())
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("can't login")
        data = response.read()
        conn.close()

        doc = minidom.parseString(data)
        node = doc.getElementsByTagName('workspace')[0]
        entries = node.getElementsByTagName('collection')
        for entry in entries:
            album = {
                '@href': entry.getAttribute('href'),
                'atom:title': entry.getElementsByTagName('atom:title')[0].childNodes[0].data,
                'accept': None
            }
            accept = entry.getElementsByTagName('accept')
            if len(accept):
                album['accept'] = accept[0].childNodes[0].data
            if len(name) and album['atom:title'] == name:
                return album
            albums.append(album)
        return albums

    """
    create album.
    """
    def create_album(self, title, summary):
        impl = minidom.getDOMImplementation()
        doc = impl.createDocument(None, 'entry', None)
        top = doc.documentElement

        top.attributes['xmlns'] = 'http://www.w3.org/2005/Atom'
        top.attributes['xmlns:app'] = 'http://purl.org/atom/app#'

        elem = doc.createElement('title')
        elem.appendChild(doc.createTextNode(title))
        top.appendChild(elem)

        elem = doc.createElement('summary')
        elem.appendChild(doc.createTextNode(summary))
        top.appendChild(elem)

        elem = doc.createElement('content')
        top.appendChild(elem)

        body = doc.toxml(encoding='UTF-8')
        doc.unlink()

        typeinfo = urllib.splittype("http://photo.mixi.jp/atom")
        hostinfo = urllib.splithost(typeinfo[1])
        conn = httplib.HTTPConnection(hostinfo[0])
        conn.request('GET', hostinfo[1], body='', headers=self.get_headers())
        response = conn.getresponse()
        if response.status != 200:
            raise Exception("can't login")
        conn.close()

#    """
#    delete album.
#    """
#    def delete_album(self, href):
#        typeinfo = urllib.splittype(href)
#        hostinfo = urllib.splithost(typeinfo[1])
#        conn = httplib.HTTPConnection(hostinfo[0])
#        headers = self.get_headers()
#        headers['X-Http-Method-Override'] = 'DELETE'
#        conn.request('POST', hostinfo[1], body='', headers=headers)
#        response = conn.getresponse()
#        if response.status != 200:
#            raise Exception("can't login")
#        data = response.read()
#        conn.close()

#    def get_photos(self, album):
#        albums = []
#        typeinfo = urllib.splittype(album)
#        hostinfo = urllib.splithost(typeinfo[1])
#        conn = httplib.HTTPConnection(hostinfo[0])
#        conn.request('GET', hostinfo[1], body='', headers=self.get_headers())
#        response = conn.getresponse()
#        if response.status != 200:
#            raise Exception("can't login")
#        data = response.read()
#        print data
#        conn.close()

    """
    query root end point of entry server.
    """
    def upload_photo(self, album, file):
        typeinfo = urllib.splittype(album)
        hostinfo = urllib.splithost(typeinfo[1])
        conn = httplib.HTTPConnection(hostinfo[0])
        data = open(file, "rb").read()
        headers = self.get_headers()
        headers['Content-Type'] = 'image/jpeg'
        conn.request('POST', hostinfo[1], body=data, headers=headers)
        response = conn.getresponse()
        if response.status != 201:
            raise Exception("can't login")
        res = response.getheader("Location")
        conn.close()
        return res

if __name__ == '__main__':
    if len(sys.argv) < 2: sys.exit()
    service = Service(sys.argv[1], sys.argv[2])
 
    # footstamp example
    #footstamps = service.get_footstamps()
    #for footstamp in footstamps:
    #    print footstamp['id']
    #    print footstamp['title']
    #    print footstamp['link']
    #    print footstamp['updated']
    #    print footstamp['author']['tracks:image']
    #    print footstamp['author']['tracks:relation']
    #    print

    # photo example
    service.create_album("My Album", "API Test")
    print service.get_photos(album)
    photo = service.upload_photo(album, "example.jpg")
    print photo

