import sys
import os
import cgi
import datetime
import urllib
import logging
from os.path import isdir
from os.path import join as dj
import sketch.serialize
from sketch.webapp import RequestHandler
from sketch.templating import jinja
from sketch.util import hasmethod, hasvar, getmethattr, force_unicode
class Messages(object):
  info = "info"
  warning = "warning"
  error = "error"
class BaseController(RequestHandler):
  """BaseController default application controller that is inherited for other
  controllers. Implements requests, response, rendering, plugins etc.
  _Plugins = {}
  template_set = 'site'
  message = False
  message_type = None
  def pre_hook(self):
  def post_hook(self):
  # Plugin reg
  def plugin_register(self, plugin_name, plugin_inst):
    self._Plugins[plugin_name] = plugin_inst
  def attach_session(self, session):
    self.session = session
  def reg_messages(self):
    self.messages = Messages()
    #"Plugin Reg: Registering messages plugin")
    if 'message' in self.session:
      self.message = self.session['message']
      self.message_type = self.session['message_type']
      self.message_class = self.session['message_class']
      del self.session['message']
      del self.session['message_type']
      del self.session['message_class']
  #   messages
  def set_msg(self, message, message_type = None):
    return self.set_message(message, message_type)
  def set_message(self, message, message_type = None, fade = 'fade'):
    if not message_type:
        message_type =
    # use a custom session component to set the message
    self.session['message'] = message
    self.session['message_type'] = message_type
    self.session['message_class'] = fade
    # self.message_type = message_type
  #   Rendering
  def render(self, template_name, passed_vars, response_code = 200, 
          response_type=False, prettyPrint=False, template_set='site', template_theme=None):
    """Main render helper function. Wraps other rendering functions
    if not response_type:
      response_type = self.request.response_type()
    prettyPrint = bool(self.request.get('prettyPrint', False))
    if response_type == 'json':
      return self.render_json(passed_vars, response_code)
      # setup jinja
      # setup variables
      passed_vars = self.get_template_vars(passed_vars)
      passed_vars = self.get_plugin_vars(passed_vars)
      # Get template_set and template_theme
      template_set = self.get_template_set()
      template_theme = self.get_template_theme(template_set)
      #'Rendering with: template_name: %s template_theme: %s template_set: %s and variables:' % (template_name, template_theme, template_set))
      content = jinja.render(template_name, passed_vars, template_theme=template_theme, template_set=template_set)
    self.render_content(content, response_code)
  def render_json(self, template_vars=None, response_code=200, headers=None):
    template_vars = template_vars or {}
    headers = headers or {}
    pretty_print = bool(self.request.get('prettyPrint', False))
    content = force_unicode(sketch.serialize.json(template_vars, pretty=pretty_print))
    if not 'Content-Type' in headers:
      headers['Content-Type'] = "application/json; charset=utf-8"
    self.render_content(content, response_code, headers)
  def render_content(self, content, response_code=200, headers=[]):
    """The actual function that will render content back into the response
    :param content: Content to be rendered
    :param response_code: HTTP response code
    :param headers: Response headers
    if len(headers) > 0:
      for hn, hv in headers:
        self.response.headers[hn] = hv
  def render_error(self, message = False, code = 404):
    self.render('error', {
        'code': '%d - %s' % (code, self.response.http_status_message(code)),
        'message': message
    }, code, template_set='sketch', template_theme='default')
  def render_feed(self, template_name, template_vars):
    template_extension = 'xml'
    template_vars['buildDate'] =
    template_vars = self.get_template_vars(template_vars)
    template_set = self.get_template_set()
    template_theme = self.get_template_theme(template_set)
    content = jinja.render(template_name, template_vars, template_theme=template_theme, template_set=template_set, template_extension=template_extension)    
    headers = [('Content-Type', "application/%s; charset=utf-8" % ('xml'))]
    return self.render_content(content, 200, headers)
  def render_admin(self, template_name, vars):
    return self.render(template_name, vars, template_folder='admin')
  def render_sketch(self, template_name, vars):
    vars['admin'] = True
    return self.render(template_name, vars, template_folder='sketch')
  def get_styles(self, template_vars):
    if not hasattr(self, 'styles'):
      return template_vars
    styles_dict = getmethattr(self, 'styles')
    styles_tmp = ""
    for style_path in styles_dict:
      style_name = ""
      styles_tmp = styles_tmp + "<link id=\"%s\" rel=\"stylesheet\" href=\"%s\" type=\"text/css\">" % (style_name, style_path)
    template_vars['styles'] = styles_tmp
    return template_vars
  def get_javascripts(self, template_vars):
    """Will read the javascripts to be included, create the tags and include
    them as part of the template variables
    :param template_vars: Template variable dict
    if not hasattr(self, 'javascripts'):
      return template_vars
    scripts_dict = getmethattr(self, 'javascripts')
    js_tmp = ""
    for script_name, script_val in scripts_dict.iteritems():
      script_src = ""
      if 'base_dir' in script_val:
        script_src = script_val['base_dir']
      for script_uri in script_val['src']:
        if 'version' in script_val:
          script_uri = script_uri + "?%s" % script_val['version']
        js_tmp = js_tmp + "\t<script type=\"text/javascript\" src=\"%s\"></script>\n" % (script_src + script_uri)
    template_vars['javascripts'] = js_tmp
    return template_vars
  def get_template_set(self):
    if hasattr(self, 'template_set'):
      return getmethattr(self, 'template_set')
    if (self.config.default_template_set):
      return self.config.default_template_set
    raise Exception('no template set specified')
  def get_template_theme(self, template_set=None):
    if template_set in self.config.template_themes:
      return self.config.template_themes[template_set]
    if hasattr(self, 'template_theme'):
      return getmethattr(self, 'template_theme')
    if (self.config.default_template_theme):
      return self.config.default_template_theme
    raise Exception('no template theme specified')
  def get_template_vars(self, template_vars):
    if type(template_vars) != dict:
      template_vars = {'_vars': template_vars}
    additional = {
      # 'session': self.session,
      # 'user': False,
        # 'title': 'test'
        # 'title': self.conf_get('title')
    # if 'auth' in self.session:
    #   additional['loggedin'] = True
    #   additional['username'] = self.session.get('username', '')
    #   additional['user'] = self.user
    # if self.message:
    #   additional['message'] = self.message
    #   additional['message_type'] = self.message_type
    #   additional['message_class'] = self.message_class
    if hasmethod(self, 'template_wrapper'):
      template_vars = self.template_wrapper(variables=template_vars)
    additional = self.get_javascripts(additional)
    additional = self.get_styles(additional)
    return dict(template_vars, **additional)
  def render_blob(self, blob_key_or_info, filename=None):
    """Render a file from the GAE blobstore
    :param blog_key_or_info: A key for the blog
    :param filename: (optional) Name of file in user download
    if isinstance(blob_key_or_info, blobstore.BlobInfo):
      blob_key = blob_key_or_info.key()
      blob_info = blob_key_or_info
      blob_key = blob_key_or_info
      blob_info = None
    self.response.headers[blobstore.BLOB_KEY_HEADER] = str(blob_key)
    del self.response.headers['Content-Type']
    def saveas(filename):
      if isinstance(filename, unicode):
        filename = filename.encode('utf-8')
      self.response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename
    if filename:
      if isinstance(filename, basestring):
      elif blob_info and filename:
        raise ValueError("problem with filename to save as")
  #   helpers
  def get_plugin_vars(self, vars):
    for plugin in self._Plugins:
      if hasattr(self._Plugins[plugin], "render"):
        val_dict = self._Plugins[plugin].render()
        if type(val_dict) == type({}):
          for temp_var in val_dict:
            if not vars.has_key(temp_var):
              vars[temp_var] = val_dict[temp_var]
              logging.error("Did not get a valid dict type from plugin %s" % plugin)
    return vars
  def get_param_dict(self):
    params = {}
    for argument in self.request.arguments():
      params[argument] = self.request.get(argument)
    return params
  #   Rendering Engines
  def render_django(self, template_name, vars, response_type = False):
    """Given a template name and variables will render the template using
    the default Django template rendering engine 
    :param template_name: Name of template
    :param vars: Template variables
    @TODO clean out the 'get_template_path' stuff and put that in render
    @TODO this should only be rendering, none of the fancy content stuff
    # from google.appengine.dist import use_library
    from google.appengine.ext.webapp import template
    if not response_type:
        response_type = self.request.response_type()
    vars = self.get_template_vars(vars)
    vars = self.get_plugin_vars(vars)
    if response_type in ['xml', 'json']:
        serial_f = getattr(sketch.serialize, response_type)
        content = serial_f(vars)
        self.response.headers['Content-Type'] = "application/%s; charset=utf-8" % (response_type)
        content = template.render(self.get_template_path(template_name, response_type), vars)
    return content
  #   Conveniance Methods
  def debug(self):
    return self.config.is_debug
  def is_dev(self):
    return self.config.is_dev
  def is_staging(self):
    return self.config.is_staging
  def is_live(self):
    return self.config.is_live
  def env(self):
    return self.config.enviro or None
  def enviro(self):
    return self.config.enviro
class AdminController(BaseController):
  """A custom controller that restricts permissions to only those users who are
  an administrator
  template_path = os.path.join('')
  def __call__(self, _method, *args, **kwargs):
    if not self.user:
    if not self.user.admin:
    super(AdminController, self).__call__(_method, *args, **kwargs)