# -*- Mode: Python; -*-
# -*- coding: utf-8 -*-
# vi:si:et:sw=2:sts=2:ts=2
import time 

from turbogears import controllers, expose, validate, error_handler
from model import *
from turbogears import identity, redirect
from cherrypy import request, response
import cherrypy

# import logging
# log = logging.getLogger("oilarchive.controllers")

from oilarchive import json

import oilcache
from forms import forms
from sortname import sortname

def httpExpires(sec):
  return cherrypy.lib.httptools.HTTPDate(time.gmtime(time.mktime(time.gmtime()) + sec))

def _default_search_values():
  return  dict(q = '', f = 'all', s = 'title', o = 0, n = 60, l = 'all', v = 'icon', length = 0)

class View:
  @expose(template=".templates.view")
  def view(self, item):
    search = cherrypy.session.get('search', _default_search_values())
    return dict(item = item, search = search)

  def icon(self, item):
    response.headerMap['Content-Type'] = "image/png"
    cherrypy.response.headerMap["Expires"] = httpExpires(60*60*24*30)
    return oilcache.loadIcon(item)
    
  def icon_reflection(self, item):
    response.headerMap['Content-Type'] = "image/png"
    cherrypy.response.headerMap["Expires"] = httpExpires(60*60*24*30)
    return oilcache.loadIconReflection(item)
  
  @expose()
  def default(self, id, *args, **kw):
    try:
      item = ArchiveItem.byHashId(id)
    except:
      raise redirect("/")
    if not args:
      return self.view(item)
    elif args[0].startswith('icon.'):
      return self.icon(item)
    elif args[0].startswith('icon_reflection.'):
      return self.icon_reflection(item)
    elif args[0] == 'update':
      item.archive.updateItem(item.archiveItemId)
      raise redirect("/view/%s" % item.hashId)
    elif args[0] == 'json':
      return item.json

class Admin:
  @expose('.templates.admin_index')
  def index(self):
    return dict()
    
  @expose('.templates.admin_archives')
  def archives(self, tg_errors=None):
    if tg_errors:
      flash("There was a problem with the form!")
    return dict(
      add_archive = forms.add_archive, 
      archives = Archive.select(orderBy = "archiveName"),
    )
    
  @expose()
  @validate(form = forms.add_archive)
  @error_handler(archives)
  def archives_add(self, **data):
    print data
    try:
      url = "%s?metadata=1" % data['archiveUrl']
      result = simplejson.loads(read_url(url))
      print result
    except:
      result = None
    if result and result.has_key('name') \
              and result.has_key('id') \
              and result.has_key('ttl'):
      archiveId = result['id']
      archiveName = result['name']
      ttl = int(result['ttl'])
      if result.has_key('icon'):
        icon = result['icon']
      else:
        icon = ''
    else:
      tg_errors ="Not a valid JSON Backend"
      return "FIXME"
    new = Archive(
      archiveName = archiveName,
      archiveId = archiveId,
      archiveUrl = data['archiveUrl'],
      icon = icon,
      ttl = ttl,
      hashId = "%s" % time.mktime(time.localtime()),
      )
    new.setHashId()
    raise redirect('archives')
    
  @expose('.templates.admin_sortnames')
  def sortnames(self, tg_errors=None):
    if tg_errors:
      flash("There was a problem with the form!")
    q = SortName.select(orderBy="name")
    names = "\n".join([i.name for i in q])
    sortnames_values = dict(names = names)
    return dict(sortnames_values = sortnames_values, sortnames_form = forms.sortnames)
  
  @expose()
  @validate(form = forms.sortnames)
  @error_handler(sortnames)
  def sortnames_save(self, **data):
    names = data['names']
    if names:
      for b in SortName.select():
        SortName.delete(b.id)
      names = names.split('\n')
      for name in names:
        SortName(name = name)
    raise redirect('sortnames')
    
class Api:
  @expose()
  def sortname(self, name):
    sname = sortname(name)
    return dict(sortname = sname, name = name)


class ArchiveJavascript:
  @expose()
  def default(self, name):
    name = name.split('.')[0]
    archive = Archive.byHashId(name)
    response.headerMap['Content-Type'] = "application/x-javascript"
    cherrypy.response.headerMap["Expires"] = httpExpires(60) #(60*60*24*30)
    return archive.js
    
class ArchiveStyleSheet:
  @expose()
  def default(self, name):
    name = name.split('.')[0]
    archive = Archive.byHashId(name)
    response.headerMap['Content-Type'] = "text/css"
    cherrypy.response.headerMap["Expires"] = httpExpires(60) #(60*60*24*30)
    return archive.css

class ArchiveIcon:
  @expose()
  def default(self, name):
    name = name.split('.')[0]
    archive = Archive.byHashId(name)
    response.headerMap['Content-Type'] = "image/png"
    cherrypy.response.headerMap["Expires"] = httpExpires(60*60*24*30)
    return oilcache.loadArchiveIcon(archive)

class Root(controllers.RootController):
  view = View()
  admin = Admin()
  api = Api()
  js = ArchiveJavascript()
  css = ArchiveStyleSheet()
  icon = ArchiveIcon()
  
  @expose()
  def redirect(self, *kw, **args):
    url = "?".join(cherrypy.request.browserUrl.split('?')[1:])
    raise redirect(url)
  
  @expose(template=".templates.login")
  def login(self, forward_url=None, previous_url=None, *args, **kw):
    if not identity.current.anonymous \
          and identity.was_login_attempted() \
          and not identity.get_identity_errors():
          raise redirect(forward_url)

    forward_url=None
    previous_url= request.path

    if identity.was_login_attempted():
      msg=_("The credentials you supplied were not correct or "
             "did not grant access to this resource.")
    elif identity.get_identity_errors():
      msg=_("You must provide your credentials before accessing "
             "this resource.")
    else:
      msg=_("Please log in.")
      forward_url= request.headers.get("Referer", "/")
        
    response.status=403
    return dict(message=msg, previous_url=previous_url, logging_in=True,
                original_parameters=request.params,
                forward_url=forward_url)

  @expose()
  def logout(self):
      identity.current.logout()
      raise redirect("/")
  

  _sort_map = {
    'id': 'hashId',
    'author': 'author_sort',
    'releasedate': 'rel_date',
    'title': 'title_sort',
    'date': 'rel_date',
  }

  def get_sort(self, s):
    s = str(self._sort_map.get(s, s))
    if s in ('rel_date', 'size', 'pub_date'):
      s = '-%s' % s
    return s

  _field_map = {
    'title': ArchiveItem.q.title,
    'author': ArchiveItem.q.author,
    'genre': ArchiveItem.q.genre,
    'date': ArchiveItem.q.relDate,
  }

  _search_map = {
    'releasedate': 'rel_date',
  }

  @expose(template=".templates.iconview")
  def search(self, q = '', f = None, s = None, o = -1, n = None, l = None, v = None):
    search = cherrypy.session.get('search', _default_search_values())
    if not v:
      v = search['v']
    if not l:
      l = search['l']
    if not n:
      n = search['n']
    if o == -1:
      o = search['o']
    if not s:
      s = search['s']
    if not f:
      f = search['f']

    o = int(o)
    n = int(n)
    
    search = dict(q = q, f = f, s = s, o = o, n = n, l = l, v = v)

    tg_template = ".templates.iconview"
    if v == 'list':
      tg_template = ".templates.listview"
    if v == 'quote':
      tg_template = ".templates.quoteview"

    orderBy = [self.get_sort(s), 'title_sort', 'rel_date']
    if q:
      q = q.encode('utf-8')
      if f=='all':
        items = queryArchive(q, s)
      elif f in ('title', 'author', 'genre', 'date'):
        items = ArchiveItem.select(LIKE(self._field_map[f], '%'+q+'%') , orderBy=orderBy)
    else:
      items = ArchiveItem.select(orderBy = orderBy)
    sort = s
    if sort.startswith('-'):
      sort = sort[1:]
    sort = self._search_map.get(sort, sort)
    sort = self._sort_map.get(sort, sort)
    print sort
    if type(items) == list:
      search['length'] = len(items)
    else:
      search['length'] = items.count()
    cherrypy.session['search'] = search
    return dict(items = items[o:o+n], sort = sort, search = search, tg_template = tg_template)

  @expose(template=".templates.listview")
  # @identity.require(identity.in_group("admin"))
  def default(self, hashID = '', **args):
    if hashID and len(hashID) == 32:
      return self.view(hashID, args)
    return self.search(**args)

