import os
import sys
import logging
import sketch
import buckley
import datetime
 
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.ext import db
from buckley.models import Post, Image, Source
from sketch.util.feeds import find_icons, discover_feeds
from sketch.vendor.embedly import Embedly
from sketch.vendor.markdown import markdown
 
class Index(buckley.AdminController):
  def get(self, path = None):
    return self.redirect('/admin/settings')
 
class Settings(buckley.AdminController):
  def get(self, val=None):
    logging.info(self.config)
    self.render('settings', {
      'settings': self.config
    })
 
  def post(self):
    self.render_error('not yet implemented')
 
class Statuses(buckley.AdminController):
  def get(self, action=None, key=None):
    if action:
      if action == 'delete':
        status = Post.get_single_by_key(key)
        status.delete()
        return self.redirect_back('deleted')
      return self.redirect_back('noaction')
    posts = Post.get_statuses(num=100, cached=False)
    self.render('statuses', {
      'posts': posts,
      'post_type': 'status'
    })
 
  def post(self, action=None, key=None):
    title = self.request.get('title', '').encode('ascii', 'ignore')
    link = self.request.get('link', '').encode('ascii', 'ignore')
    content_html = ""
    thumbnail = None
    link_type = 'link'
    embed_html = ""
    source = None
    _embedly = Embedly(dev_token=self.config.embedly_key)
 
    if not title and not link:
      return self.redirect_back('err')
 
    # get embed info
    try:
      if link:
        _e = _embedly.get_embed(link)
        embed = {}
        logging.info(_e)
        if type(_e) == type({}):
          embed['title'] = _e['title']
          embed['description'] = _e['description']
          embed['url'] = _e['url']
          embed['source'] = _e['provider_name']
          link_type = _e['type']
          if 'html' in _e:
            embed_html = _e['html']
 
          title = embed['title']
          content_html = "<p>" + embed['description'] + "</p>"
          link = embed['url']
 
          source = Source.get_by_web(_e['provider_url'])
          if not source:
            logging.info('new source')
            name = _e['provider_name']
            src_icon = find_icons(_e['provider_url'])
            logging.info(src_icon)
            feed_url = discover_feeds(_e['provider_url'])
            logging.info(feed_url)
 
            if src_icon:
              icon = Image(
                origurl = src_icon
              )
              icon.put()
            else:
              icon = None
 
            source = Source(
              name = name,
              web = _e['provider_url'],
            )
            if icon:
              source.icon = icon.key()
            if feed_url:
              source.feed = feed_url
            source.put()
 
          if 'thumbnail_url' in _e:
            url = _e['thumbnail_url']
            width = _e['thumbnail_width']
            height = _e['thumbnail_height']
 
            thumbnail = Image(
              origurl = url,
              width = width,
              height = height
            )
            r = thumbnail.put()
          else:
            logging.info('no thumb')
        else:
          embed = None
    except Exception, e:
      logging.exception(e)
      embed = None
 
    try:
      categories = [db.Category('none')]
      author = users.get_current_user()
      now = datetime.datetime.now()
 
      status = Post(
        author = author,
        title = title,
        content_link = link,
        content_html = content_html,
        embed_html = embed_html,
        link_type = link_type,
        post_type = "status",
        status = "published",
        pubdate = now,
        categories = categories
      )
      if source:
        status.content_link_src = source.key()
      if thumbnail:
        status.thumbnail = thumbnail.key()
      r = status.put()
      self.redirect('/admin/status?new=%s' % (str(r)))
    except Exception, e:
      logging.exception(e)
      return self.redirect_back('error')
 
class Posts(buckley.AdminController):
  def extract_excerpt(self, content):
    pos = content.find("--")
    if pos < 1:
      return None
    return content[:pos]
 
  def get(self, action=None, key=None):
    if action:
      if action == 'edit' and key:
        posts = Post.get_single_by_key(key)
        self.render('posts.edit', {
          'post': posts,
          'post_type': 'post'
        })
      elif action == 'new':
        self.render('posts.edit', {
          'post': {}
        })
      elif action == 'publish':
        post = Post.get_single_by_key(key)
        post.publish()
        return self.redirect_back()
      else:
        self.redirect_back()
    else:
      posts = Post.get_posts(num=100, cached=False)
      self.render('posts', {
        'posts': posts,
        'post_type': 'post'
      })
 
  def post(self, action=False, key=False):    
    title = self.request.get('title', "").encode('ascii', 'ignore')
    subtitle = self.request.get('subtitle', "").encode('ascii', 'ignore')
    content = self.request.get('content', "").encode('ascii', 'ignore')
    ptype = self.request.get('ptype', "post")
    cached = self.request.get_checkbox('cached')
    featured = self.request.get_checkbox('featured')
 
    if not title or not content or not ptype:
      return self.redirect_back()
 
    try:
      excerpt = self.extract_excerpt(content)
      excerpt_html = markdown(excerpt)
      html = markdown(content.replace("--", '', 1))
    except Exception, e:
      logging.exception(e)
      raise e
 
    if action == 'edit' and key:
      post = Post.get_single_by_key(key)
      if not post:
        raise sketch.exception.NotFound()
 
      post.title = title
      post.subtitle = subtitle
      post.excerpt = excerpt
      post.excerpt_html = excerpt_html      
      post.content = content
      post.content_html = html
      post.featured = featured
      post.cached = cached
 
      if self.request.get('action') == 'publish':
        post.publish()
 
      if post.put():
        memcache.flush_all()
        self.redirect('/admin/%s/edit/%s' % (ptype, str(post.key()) + '?success'))
      else:
        raise sketch.exception.NotFound()
    else:      
      categories = [db.Category('none')]
      author = users.get_current_user()
 
      post = Post(
        author = author,
        title = title,
        subtitle = subtitle,
        excerpt = excerpt,
        excerpt_html = excerpt_html,
        content = content,
        content_html = html,
        post_type = ptype,
        status = "draft",
        categories = categories,
        featured = featured,
        cached = cached,
        stub = self.slugify(title)
      )
      r = post.put()
      self.redirect('/admin/%s/edit/%s' % (ptype, str(r)))
 
class Pages(buckley.AdminController):
  def get(self, action=None, key=None):
    if action:
      if action == 'edit' and key:
        page = Post.get_single_by_key(key)
        self.render('posts.edit', {
          'post': page,
          'post_type': 'page'
        })
      elif action == 'new':
        self.render('posts.edit', {
          'post': {},
          'post_type': 'page'
        })
      elif action == 'publish':
        post = Post.get_single_by_key(key)
        post.publish()
        return self.redirect_back()
      else:
        self.redirect_back()
    else:
      posts = Post.get_pages(num=100, cached=False)
      self.render('posts', {
        'posts': posts,
        'post_type': 'page'
      })
 
 
class Comments(buckley.AdminController):
  def get(self, path = None):
    return self.render('comments', {}) 
 
 
class Cache(buckley.AdminController):  
  def render_cache(self, template_name, vars):
    template_path = os.path.join(os.path.dirname(__file__), '..', 'templates', template_name + '.html')
    content = template.render(template_path, self.get_template_vars(vars))
    return content
 
  def get_memcache(self, posts):
    mem = []
    cache_types = ['post', 'models']
    for post in posts:
      for cache_type in cache_types:
        m = {}
        if cache_type is 'post':
          m['post'] = True
        m['key'] = str(post.key())
        m['stub'] = post.stub
        m['memkey'] = cache_type + '.' + post.stub
        dat_key = "%s.%s" % (cache_type, post.stub)
        dat = memcache.get(dat_key)
        if dat:
          m['cached'] = True
        else:
          m['cached'] = False
        mem.append(m)
 
    dat = memcache.get("models.index")
    if dat:
      m = {
        'stub': 'index',
        'memkey': 'models.index',
        'cached': True
      }
      mem.append(m)
 
    return mem
 
  def set_memcache(self, posts):
    m_map = {}
    p_map = {}
 
    for post in posts:
      dat_key = "%s.%s" % ('post', post.stub)
      mod_key = "%s.%s" % ('models', post.stub)
      page_vars = {'tab_blog': True, 'post': post, 'src': 'page.memcache'}
      content = self.render_cache('single', page_vars)
 
      p_map[dat_key] = content
      m_map[mod_key] = post
      logging.info(mod_key)
      logging.info(post)
 
    v = memcache.set_multi(m_map)
    r = memcache.set_multi(p_map)
 
    if len(v) != 0 or len(r) != 0:
      return False
 
    return True
 
  def get_filecache(self, posts):
    files = []
    cache_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'cache'))
    if not os.path.isdir(cache_dir):
      logging.error('Admin cache: not a cache dir ' + cache_dir)
      return None
    for cfile in os.listdir(cache_dir) :
      if cfile[:1] == '.':
        continue
      m = {}
      full_path = os.path.join(cache_dir, cfile)
      m['path'] = full_path
      m['name'] = cfile
      try:
        fmt = os.path.getmtime(full_path)
        m['mtts'] = fmt
        m['mt'] = datetime.datetime.fromtimestamp(fmt)
      except Exception, e:
        pass
      files.append(m)
    for post in posts:
      m = {}
    return files
 
  def set_filecache(self, posts):
    cache_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'cache'))
    for post in posts:
      page_vars = {'tab_blog': True, 'post': post, 'src': 'page.filecache'}
      content = self.render_cache('single', page_vars)
      fp = os.path.join(cache_dir, post.stub)
      logging.info(fp)
      f = open(fp, 'w')
      f.write(content)
      f.close()
 
  def get(self, val = None):
    query = db.GqlQuery("select * from Post where post_type='post' and status='published' order by pubdate DESC")
    posts = query.fetch(100)
 
    mem = self.get_memcache(posts)
    files = self.get_filecache(posts)
    memstats = memcache.get_stats()
    filestats = {}
 
    self.render('cache', {
      'memcache': mem,
      'files': files,
      'posts': posts,
      'memstats': memstats,
      'filestats': filestats,
    })
 
  def post(self):
    action = self.request.get('action', False)
    if not action:
      return self.redirect('/admin/cache?bleh')
 
    query = db.GqlQuery("select * from Post where post_type='post' and status='published' order by pubdate DESC")
    posts = query.fetch(100)
 
    if action == 'files':
      self.set_filecache(posts)
      return self.redirect('/admin/cache?rs_files')
    if action == 'mem':
      r = self.set_memcache(posts)
      return self.redirect('/admin/cache?rs_mem=' + str(r))
    return self.redirect('/admin/cache?')
 
class CacheView(buckley.AdminController):
  def get(self, key):
    pkey = "%s.%s" % ('post', key)
    r = memcache.get(pkey)
    if r:
      self.response.clear()
      self.response.set_status(200)
      self.response.out.write(r)
      return None
    else:
      return self.render_error("not found")