# Copyright 2010 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# This is the server part of the package dashboard.
# It must be run by App Engine.

from google.appengine.api import mail
from google.appengine.api import memcache
from google.appengine.api import taskqueue
from google.appengine.api import urlfetch
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
import datetime
import logging
import os
import re
import sets
import urllib2

# local imports
from auth import auth
import toutf8
import const

template.register_template_library('toutf8')

# Storage model for package info recorded on server.
class Package(db.Model):
    path = db.StringProperty()
    web_url = db.StringProperty()           # derived from path
    count = db.IntegerProperty()            # grand total
    week_count = db.IntegerProperty()       # rolling weekly count
    day_count = db.TextProperty(default='') # daily count
    last_install = db.DateTimeProperty()

    # data contributed by gobuilder
    info = db.StringProperty()  
    ok = db.BooleanProperty()
    last_ok = db.DateTimeProperty()

    def get_day_count(self):
        counts = {}
        if not self.day_count:
            return counts
        for d in str(self.day_count).split('\n'):
            date, count = d.split(' ')
            counts[date] = int(count)
        return counts

    def set_day_count(self, count):
        days = []
        for day, count in count.items():
            days.append('%s %d' % (day, count))
        days.sort(reverse=True)
        days = days[:28]
        self.day_count = '\n'.join(days)

    def inc(self):
        count = self.get_day_count()
        today = str(datetime.date.today())
        count[today] = count.get(today, 0) + 1
        self.set_day_count(count)
        self.update_week_count(count)
        self.count += 1

    def update_week_count(self, count=None):
        if count is None:
            count = self.get_day_count()
        total = 0
        today = datetime.date.today()
        for i in range(7):
            day = str(today - datetime.timedelta(days=i))
            if day in count:
                total += count[day]
        self.week_count = total


# PackageDaily kicks off the daily package maintenance cron job
# and serves the associated task queue.
class PackageDaily(webapp.RequestHandler):

    def get(self):
        # queue a task to update each package with a week_count > 0
        keys = Package.all(keys_only=True).filter('week_count >', 0)
        for key in keys:
            taskqueue.add(url='/package/daily', params={'key': key.name()})

    def post(self):
        # update a single package (in a task queue)
        def update(key):
            p = Package.get_by_key_name(key)
            if not p:
                return
            p.update_week_count()
            p.put()
        key = self.request.get('key')
        if not key:
            return
        db.run_in_transaction(update, key)
 

class Project(db.Model):
    name = db.StringProperty(indexed=True)
    descr = db.StringProperty()
    web_url = db.StringProperty()
    package = db.ReferenceProperty(Package)
    category = db.StringProperty(indexed=True)
    tags = db.ListProperty(str)
    approved = db.BooleanProperty(indexed=True)


re_bitbucket = re.compile(r'^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-zA-Z0-9_.\-]+)(/[a-z0-9A-Z_.\-/]+)?$')
re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg|git)(/[a-z0-9A-Z_.\-/]+)?$')
re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)+$')
re_launchpad = re.compile(r'^launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]+)?$')

def vc_to_web(path):
    if re_bitbucket.match(path):
        m = re_bitbucket.match(path)
        check_url = 'http://' + m.group(1) + '/?cmd=heads'
        web = 'http://' + m.group(1) + '/'
    elif re_github.match(path):
        m = re_github_web.match(path)
        check_url = 'https://raw.github.com/' + m.group(1) + '/' + m.group(2) + '/master/'
        web = 'http://github.com/' + m.group(1) + '/' + m.group(2) + '/'
    elif re_googlecode.match(path):
        m = re_googlecode.match(path)
        check_url = 'http://'+path
        if not m.group(2):  # append / after bare '/hg' or '/git'
            check_url += '/'
        web = 'http://code.google.com/p/' + path[:path.index('.')]
    elif re_launchpad.match(path):
        check_url = web = 'https://'+path
    else:
        return False, False
    return web, check_url

re_bitbucket_web = re.compile(r'bitbucket\.org/([a-z0-9A-Z_.\-]+)/([a-z0-9A-Z_.\-]+)')
re_googlecode_web = re.compile(r'code.google.com/p/([a-z0-9\-]+)')
re_github_web = re.compile(r'github\.com/([a-z0-9A-Z_.\-]+)/([a-z0-9A-Z_.\-]+)')
re_launchpad_web = re.compile(r'launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]+)?')
re_striphttp = re.compile(r'https?://(www\.)?')

def find_googlecode_vcs(path):
    # Perform http request to path/hg or path/git to check if they're
    # using mercurial or git.  Otherwise, assume svn.
    for vcs in ['git', 'hg']:
        try:
            response = urlfetch.fetch('http://'+path+vcs, deadline=1)
            if response.status_code == 200:
                return vcs
        except: pass
    return 'svn'

def web_to_vc(url):
    url = re_striphttp.sub('', url)
    m = re_bitbucket_web.match(url)
    if m:
        return 'bitbucket.org/'+m.group(1)+'/'+m.group(2)
    m = re_github_web.match(url)
    if m:
        return 'github.com/'+m.group(1)+'/'+m.group(2)
    m = re_googlecode_web.match(url)
    if m:
        path = m.group(1)+'.googlecode.com/'
        vcs = find_googlecode_vcs(path)
        return path + vcs
    m = re_launchpad_web.match(url)
    if m:
        return m.group(0)
    return False

MaxPathLength = 100
CacheTimeout = 3600

class PackagePage(webapp.RequestHandler):
    def get(self):
        if self.request.get('fmt') == 'json':
            return self.json()

        html = memcache.get('view-package')
        if not html:
            tdata = {}

            q = Package.all().filter('week_count >', 0)
            q.order('-week_count')
            tdata['by_week_count'] = q.fetch(50)

            q = Package.all()
            q.order('-last_install')
            tdata['by_time'] = q.fetch(20)

            q = Package.all()
            q.order('-count')
            tdata['by_count'] = q.fetch(100)

            path = os.path.join(os.path.dirname(__file__), 'package.html')
            html = template.render(path, tdata)
            memcache.set('view-package', html, time=CacheTimeout)

        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
        self.response.out.write(html)

    def json(self):
        json = memcache.get('view-package-json')
        if not json:
            q = Package.all()
            s = '{"packages": ['
            sep = ''
            for r in q:
                s += '%s\n\t{"path": "%s", "last_install": "%s", "count": "%s"}' % (sep, r.path, r.last_install, r.count)
                sep = ','
            s += '\n]}\n'
            json = s
            memcache.set('view-package-json', json, time=CacheTimeout)
        self.response.set_status(200)
        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        self.response.out.write(json)

    def can_get_url(self, url):
        try:
            urllib2.urlopen(urllib2.Request(url))
            return True
        except:
            return False

    def is_valid_package_path(self, path):
        return (re_bitbucket.match(path) or
            re_googlecode.match(path) or
            re_github.match(path) or
            re_launchpad.match(path))

    def record_pkg(self, path):
        # sanity check string
        if not path or len(path) > MaxPathLength or not self.is_valid_package_path(path):
            return False

        # look in datastore
        key = 'pkg-' + path
        p = Package.get_by_key_name(key)
        if p is None:
            # not in datastore - verify URL before creating
            web, check_url = vc_to_web(path)
            if not web:
                logging.error('unrecognized path: %s', path)
                return False
            if not self.can_get_url(check_url):
                logging.error('cannot get %s', check_url)
                return False
            p = Package(key_name = key, path = path, count = 0, web_url = web)

        if auth(self.request):
            # builder updating package metadata
            p.info = self.request.get('info')
            p.ok = self.request.get('ok') == "true"
            if p.ok:
                p.last_ok = datetime.datetime.utcnow()
        else:
            # goinstall reporting an install
            p.inc()
            p.last_install = datetime.datetime.utcnow()

        # update package object
        p.put()
        return True

    def post(self):
        path = self.request.get('path')
        ok = db.run_in_transaction(self.record_pkg, path)
        if ok:
            self.response.set_status(200)
            self.response.out.write('ok')
        else:
            logging.error('invalid path in post: %s', path)
            self.response.set_status(500)
            self.response.out.write('not ok')

class ProjectPage(webapp.RequestHandler):

    def get(self):
        admin = users.is_current_user_admin()
        if self.request.path == "/project/login":
            self.redirect(users.create_login_url("/project"))
        elif self.request.path == "/project/logout":
            self.redirect(users.create_logout_url("/project"))
        elif self.request.path == "/project/edit" and admin:
            self.edit()
        elif self.request.path == "/project/assoc" and admin:
            self.assoc()
        else:
            self.list()

    def assoc(self):
        projects = Project.all()
        for p in projects:
            if p.package:
                continue
            path = web_to_vc(p.web_url)
            if not path:
                continue
            pkg = Package.get_by_key_name("pkg-"+path)
            if not pkg:
                self.response.out.write('no: %s %s<br>' % (p.web_url, path))
                continue
            p.package = pkg
            p.put()
            self.response.out.write('yes: %s %s<br>' % (p.web_url, path))

    def post(self):
        if self.request.path == "/project/edit":
            self.edit(True)
        else:
            data = dict(map(lambda x: (x, self.request.get(x)), ["name","descr","web_url"]))
            if reduce(lambda x, y: x or not y, data.values(), False):
                data["submitMsg"] = "You must complete all the fields."
                self.list(data)
                return
            p = Project.get_by_key_name("proj-"+data["name"])
            if p is not None:
                data["submitMsg"] = "A project by this name already exists."
                self.list(data)
                return
            p = Project(key_name="proj-"+data["name"], **data)
            p.put()
		
            path = os.path.join(os.path.dirname(__file__), 'project-notify.txt')
            mail.send_mail(
                sender=const.mail_from,
                to=const.mail_submit_to,
                subject=const.mail_submit_subject,
                body=template.render(path, {'project': p}))

            self.list({"submitMsg": "Your project has been submitted."})

    def list(self, additional_data={}):
        cache_key = 'view-project-data'
        tag = self.request.get('tag', None)
        if tag:
            cache_key += '-'+tag
        data = memcache.get(cache_key)
        admin = users.is_current_user_admin()
        if admin or not data:
            projects = Project.all().order('category').order('name')
            if not admin:
                projects = projects.filter('approved =', True)
            projects = list(projects)

            tags = sets.Set()
            for p in projects:
                for t in p.tags:
                    tags.add(t)

            if tag:
                projects = filter(lambda x: tag in x.tags, projects)

            data = {}
            data['tag'] = tag
            data['tags'] = tags
            data['projects'] = projects 
            data['admin']= admin
            if not admin:
                memcache.set(cache_key, data, time=CacheTimeout)

        for k, v in additional_data.items():
            data[k] = v

        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
        path = os.path.join(os.path.dirname(__file__), 'project.html')
        self.response.out.write(template.render(path, data))

    def edit(self, save=False):
        if save:
            name = self.request.get("orig_name")
        else:
            name = self.request.get("name")

        p = Project.get_by_key_name("proj-"+name)
        if not p:
            self.response.out.write("Couldn't find that Project.")
            return

        if save:
            if self.request.get("do") == "Delete":
                p.delete()
            else:
                pkg_name = self.request.get("package", None)
                if pkg_name:
                    pkg = Package.get_by_key_name("pkg-"+pkg_name)
                    if pkg:
                        p.package = pkg.key()
                for f in ['name', 'descr', 'web_url', 'category']:
                    setattr(p, f, self.request.get(f, None))
                p.approved = self.request.get("approved") == "1"
                p.tags = filter(lambda x: x, self.request.get("tags", "").split(","))
                p.put()
            memcache.delete('view-project-data')
            self.redirect('/project')
            return

        # get all project categories and tags
        cats, tags = sets.Set(), sets.Set()
        for r in Project.all():
            cats.add(r.category)
            for t in r.tags:
                tags.add(t)

        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
        path = os.path.join(os.path.dirname(__file__), 'project-edit.html')
        self.response.out.write(template.render(path, { 
            "taglist": tags, "catlist": cats, "p": p, "tags": ",".join(p.tags) }))

    def redirect(self, url):
        self.response.set_status(302)
        self.response.headers.add_header("Location", url)

def main():
    app = webapp.WSGIApplication([
        ('/package', PackagePage),
        ('/package/daily', PackageDaily),
        ('/project.*', ProjectPage),
        ], debug=True)
    run_wsgi_app(app)

if __name__ == '__main__':
    main()
