#----------------------------------------------------------------------
# Authors:
#   Luis Felipe Strano Moraes
#   Bruno Dilly
#
# Copyright (C) 2007 Authors
#
# Released under GNU GPL, read the file 'COPYING' for more information
# ----------------------------------------------------------------------

import httplib 
import string
import mimetools
# We're not using mimetypes nor urllib2 because they are not available
# on PyS60

def get_imc_list():
	"""
	Returns the list of available IMC sites, where each IMC is defined as :
	(name, cms, cms_version, languages, publishing_url)
	"""

	# list of imc sites available and supported by this lib
	# an entry consists of : "Name", "CMS", "CMS_version", "languages supported", "Publishing URL"
	imc_sites = [(u"SF-Active test site", "sfactive", "0.98", [("english",1), ("castellano",2), ("german",3)] , "http://sfa.plentyfact.net/publish.php"),
			(u"Samizdat test site", "samizdat", "0.6.0", [("english","en")], "http://samizdat.axxs.org/message/publish")]
	return imc_sites

def get_information():
	arguments = {
		"language": "",
		"title": "",
		"author": "",
		"summary": "",
		"article": "",
	}
        optional = {
		"address": "",
		"phone": "",
		"email": "",
		"homepage": "",
		"html": False,
		"media_titles": [],
		"media_files": [],
		"media_comments": [],
	}
	return arguments, optional

def sfactive_fields(arguments, optional):
	fields = []
	files = []

	fields.append(["top_id", ""])

	# TODO : should be :
	#        - non null
	#        - smaller than 90 chars
	fields.append(["heading", arguments["title"]])

	fields.append(["language_id", str(arguments["language"])])

	fields.append(["category[]", "0"])

	# TODO : should be : 
	# 	 - non null
	# 	 - smaller than 45 chars
	fields.append(["author", arguments["author"]])

	# TODO : should be :
	# 	 - smaller than 80 chars
	fields.append(["contact", optional["email"]])

	# TODO : should be :
	# 	 - smaller than 80 chars
	fields.append(["phone", optional["phone"]])

	# TODO : should be :
	# 	 - smaller than 160 chars
	fields.append(["address", optional["address"]])

	# TODO : should be :
	#        - non null
	#        - smaller than 6 lines (htf do I test this ?)
	fields.append(["summary", arguments["summary"]])

	# TODO : should be :
	# 	 - smaller than 160 chars
	fields.append(["link", optional["homepage"]])

	# TODO : should be :
	#        - non null
	fields.append(["article", arguments["article"]])

	if optional["html"]: 
		html = "h"
	else:
		html = "t" 
	fields.append(["artmime", html])

	fields.append(["file_count", "0"])

	fields.append(["publish", "Publish"])

	# Appends files
	for i in range(0, len(optional["media_files"])):
		file = []
		file.append("linked_file_" + str(i+1))
		file.append(lambda: open(optional["media_files"][i],'rb').read())
		file.append("")
		files.append(file)
		if i > 0:
			fields.append(["linked_file_title_" + str(i+1), 
					optional["media_titles"][i]])
			fields.append(["linked_file_comment_" + str(i+1),
					optional["media_comments"][i]])
	return fields, files

def mir_fields(arguments, optional):
	fields = []
	files = []
	# Appends fields
	fields.append(("to_language", str(arguments["language"])))
	fields.append(("title", arguments["title"]))
	fields.append(("creator", arguments["author"]))
	fields.append(("description", arguments["summary"]))
	fields.append(("content_data", arguments["article"]))
	fields.append(("creator_email", optional["email"]))
	fields.append(("creator_main_url", optional["homepage"]))
	if optional["html"]:
		fields.append(("is_html", "1"))
	else:
		fields.append(("is_html", "0"))
	num_items = len(optional["media_files"])
	if num_items == 0:
		num_items = 1
	fields.append(("nrmediaitems", str(num_items)))
	fields.append(("post", "Publique"))
	# Appends files
	if len(optional["media_files"]) == 0:
		files.append(("media1_title", "", ""))
	else:
		for i in range(0, len(optional["media_files"])):
			file = []
			file.append("media" + str(i+1) + "_title")
			file.append(lambda: open(optional["media_files"][i],'rb').read())
			file.append(optional["media_titles"][i])
			files.append(file)
	return fields, files

def samizdat_fields(arguments, optional):
	fields = []
	files = []
	# Appends fields
	fields.append(("title", arguments["title"]))
	fields.append(("rating", ""))
        fields.append(("focus", ""))
        fields.append(("lang", arguments["language"]))
        fields.append(("desc", ""))
        fields.append(("open", "false"))
        fields.append(("action", ""))
	fields.append(("confirm", "Confirm"))
	# Appends files
	if len(optional["media_files"]) == 0:
                print "sem arquivos"
		fields.append(("upload", ""))
		fields.append(("body", arguments["article"]))
		fields.append(("format", ""))
	else:
		print "com arquivos"
		preview_fields = []
		preview_files = []
		preview_fields.append(("title", arguments["title"]))
		preview_fields.append(("body", arguments["article"]))
		preview_fields.append(("rating", "1"))
		preview_fields.append(("format", ""))
		preview_fields.append(("preview", "Preview"))
		preview_files.append(("file", lambda: open(optional["media_files"][0],'rb').read(), optional["media_files"][0]))
		status, reason, answer = post_multipart("samizdat.axxs.org", "/message/publish", preview_fields, preview_files)
                print status, reason, answer
		fields.append(("body", ""))
		fields.append(("upload", "true"))
		fields.append(("format", "image/jpeg"))
	return fields, files


def publish(imc_index, arguments, optional):
	"""
	Does the actual publishing, returning True if everything goes ok, False otherwise
	imc -> to which imc collective the news should be published
	arguments -> obligatory arguments (such as title and body)
	optional -> optional stuff (such as images)
	"""
	imc_sites = get_imc_list()
	imc = imc_sites[imc_index]
	imc_url = imc[4]
	imc_type = imc[1]

	host = string.split(imc_url, '/')[2]
	selector = "/" + string.split(imc_url, '/', 3)[-1]

	fields = []
	files = []

	if imc_type == "sfactive":
		fields, files = sfactive_fields(arguments, optional)
	elif imc_type == "mir":
		fields, files = mir_fields(arguments, optional)
	elif imc_type == "samizdat":
		fields, files = samizdat_fields(arguments, optional)
	status, reason, answer = post_multipart(host, selector, fields, files)
        print status, reason, answer
	return True
	
# Modified from
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
def post_multipart(host, selector, fields, files):
    """
    Post fields and files to an http host as multipart/form-data.
    fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return the server's response page.
    """
    content_type, body = encode_multipart_formdata(fields, files)
    h = httplib.HTTPConnection(host)  
    headers = {
        'User-Agent': 'IMCPub',
        'Content-Type': content_type,
	'Referer': host + selector 
        }

    h.request('POST', selector, body, headers)
    res = h.getresponse()
    return res.status, res.reason, res.read()

def encode_multipart_formdata(fields, files):
    """
    fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return (content_type, body) ready for httplib.HTTP instance
    """
    BOUNDARY = mimetools.choose_boundary()
    CRLF = '\r\n'
    L = []
    # No need to URL encode as this is form text data.
    for (key, value) in fields:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"' % key)
        L.append('')
        L.append(value)
    for (key, filename, value) in files:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        L.append(value)
    L.append('--' + BOUNDARY + '--')
    L.append('')
    # ''.join() won't work here (PyS60 doesn't like it), so we do it
    # with a virtual file.
    from cStringIO import StringIO
    file_str = StringIO()
    for i in range(len(L)):
        file_str.write(L[i])
        file_str.write(CRLF)
    body = file_str.getvalue()
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

def get_content_type(filename):
    # we should guess the type, but since its not in our PyS60
    # distribution, we will just say octet.
    # return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
    # samizdat doesn't accept 'application/octet-stream' file format
    # return 'application/octet-stream' 
    return 'image/jpeg'
