#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import io
import math
from PIL import Image
from HTMLParser import HTMLParser
import sqlite3 as lite
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
define("port", default=8080, help="run on the given port", type=int)


PATH=os.path.dirname(os.path.abspath(__file__))
static_path_dir = os.path.join(PATH, 'static/fossil')
data_path_dir = "/mnt/fossils"

class MyHTMLParser(HTMLParser):
    def __init__(self):
        self.reset()
        self.ttype = "p"
        self.fed = []
    
    def handle_starttag(self, tag, attrs):
        self.ttype = str(tag)

    def handle_endtag(self, tag):
        self.ttype = "p"

    def handle_data(self, data):
        self.fed.append({"type": self.ttype,
                         "text": data.strip()})
        
    def get_data(self):
        return self.fed


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler),
            (r"/update", UpdateHandler),
            (r"/img", ImageHandler),
            (r"/download", GenFileStreamerHandler),
            (r"/getpage", PageHandler),
            #(r'/fossils/static/(.*)', tornado.web.StaticFileHandler, {'path': static_path_dir}),
        ]
        settings = dict(
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=static_path_dir,
            debug=True,
        )
        tornado.web.Application.__init__(self, handlers, **settings)


class DATA:
    def __init__(self, index=None):
        self.con = lite.connect('fossil.db')
        cur = self.con.cursor()
        with self.con:
            if index == None:
                cur.execute("SELECT * FROM Fossil ORDER BY Name LIMIT 1")
            else:
                cur.execute("SELECT * FROM Fossil WHERE Name = ?", [index])
            data = cur.fetchone()
        
        if data == None:
            raise Exception('Database: Data Id ' + str(index) + ' does not exist.')
        
        #self.index = data[0]
        print data
        
        self.name = data[0]
        parser = MyHTMLParser()
        parser.feed(data[1])
        self.desc = parser.get_data() 

        
        self.size = ("%.2f" % (data[2] / 1000000.0))
        self.left_count = data[3]
        self.top_count = data[4]
        self.front_count = data[5]
        
        self.left_width = data[7]
        self.top_width = data[8]
        self.front_width = data[9]

    #def get_index(self):
    #    return self.index
    
    def get_name(self):
        return self.name
    
    def get_desc(self):
        return self.desc
    
    def get_size(self):
        return self.size
    
    def get_left_width(self):
        return self.left_width
    
    def get_top_width(self):
        return self.top_width
    
    def get_front_width(self):
        return self.front_width
    
    def get_left_count(self):
        return self.left_count
    
    def get_top_count(self):
        return self.top_count
    
    def get_front_count(self):
        return self.front_count
    
    def slug(self, slug=None):
        if slug:
            self.slug = slug
        else:
            self.slug = "The Fossils Data"
        return self.slug
    
    def title(self, title=None):
        if title:
            self.title = title
        else:
            self.title = """Parasitoid biology preserved in mineralized fossils"""
        return self.title

    def get_list(self, page=None):
        if page == None:
            page = 1

        page_lower = (page - 1) * 10
        page_upper = page_lower + 10

        with self.con:
            cur = self.con.cursor()
            #cur.execute("SELECT * FROM Fossil WHERE Id > 0 AND Id <= 10 ORDER BY Id ASC")
            cur.execute("SELECT * FROM Fossil WHERE Id > " + str(page_lower) + " AND Id <= " + str(page_upper) + " ORDER BY Id ASC")

            data = cur.fetchall()
            
            tmp_data = []
            for i, item in enumerate(data):
                parser = MyHTMLParser()
                parser.feed(item[1])
                tmp_data.append([
                    item[0],
                    parser.get_data(),
                    "%.2f" % (item[2] / 1000000.0),
                    item[3],
                    item[4],
                    item[5],
                    item[6],
                    item[7],
                    item[8],
                    item[9]
                ])
        self.data_list = tmp_data
        return self.data_list


class PageHandler(tornado.web.RequestHandler):

    def get(self):
        page = int(self.get_argument("page", 1))
        filter_type = self.get_argument("type", "0")

        total_item_per_page = 10

        self.con = lite.connect('fossil.db')
        cur = self.con.cursor()
        with self.con:
            cur = self.con.cursor()
            if filter_type == "0":
                cur.execute("SELECT * FROM Fossil ORDER BY Id ASC")
                print "0 type"
            else:
                cur.execute("SELECT * FROM Fossil WHERE Description LIKE '%"+filter_type+"%' ORDER BY Id ASC")

            data = cur.fetchall()
            total_items = len(data)  

            for unit in data:
                print unit 

 
            lower_limit = (page - 1) * 10
            upper_limit =  lower_limit + 10

            if upper_limit > total_items:
                upper_limit = total_items
            print page, lower_limit, upper_limit
            tmp_data = []
            for i, item in enumerate(data[lower_limit:upper_limit]):
                parser = MyHTMLParser()
                parser.feed(item[1])
                tmp_data.append([
                    item[0],
                    parser.get_data(),
                    "%.2f" % (item[2] / 1000000.0),
                    item[3],
                    item[4],
                    item[5],
                    item[6],
                    item[7],
                    item[8],
                    item[9]
                ])
        output = {}
        output["data"] = tmp_data
        output["total_items"] = total_items
        delta = upper_limit - lower_limit
        if delta < 0:
            delta = 0
        output["total_items_per_page"] = delta
        output["total_pages"] = math.ceil(total_items / 10.0)
        self.write(output)


class UpdateHandler(tornado.web.RequestHandler):

    def get(self):
        index = self.get_argument("index", None)
        name = self.get_argument("name", None)
        print index, name
        selected_data = DATA(index)

        self.write({
            "name": name,
            "index": index,
            "data_size": selected_data.get_size(),
            "desc": selected_data.get_desc(),
            "top_count": selected_data.get_top_count(),
            "left_count": selected_data.get_left_count(),
            "front_count": selected_data.get_front_count()
        })


class MainHandler(tornado.web.RequestHandler):

    def get(self):
        index = self.get_argument("index", None)
        print index
        data = DATA(index)
       
        print data.get_list() 
        self.render(
            "fossil.html",
            slug = data.slug(),
            #index = data.get_index(),
            name = data.get_name(),
            title = data.title(),
            data_list = data.get_list(),
            desc = data.get_desc(),
            data_size = data.get_size(),
            left_count = data.get_left_count(),
            top_count = data.get_top_count(),
            front_count = data.get_front_count(),
            left_width = data.get_left_width(),
            top_width = data.get_top_width(),
            front_width = data.get_front_width()
        )


class GenFileStreamerHandler(tornado.web.RequestHandler):
    
    CHUNK_SIZE = 512000
    DATA_PATH = data_path_dir
    
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        cdid = self.get_argument("did")

        print cdid
        con = lite.connect('fossil.db')
        with con:
            cur = con.cursor()
            cur.execute("SELECT name FROM Fossil WHERE name = ?", [cdid])
            data_key = cur.fetchall()
            
        if len(data_key) > 0:
            file_name = str(cdid) + ".zip"
            self.path = os.path.join(
                self.DATA_PATH,
                str(cdid),
                file_name)
            self.set_header('Content-Type',
                            'application/octet-stream')
            self.set_header('Content-Disposition',
                            'attachment; filename="' + file_name)
            self.set_header("Content-Length",
                            os.path.getsize(self.path))
            self.flush()
            fd = open(self.path, "rb")
            data = fd.read(self.CHUNK_SIZE)
            while data:
                self.write(data)
                yield tornado.gen.Task(self.flush)
                data = fd.read(self.CHUNK_SIZE)
            fd.close()
        self.finish()


class ImageHandler(tornado.web.RequestHandler):
    CHUNK_SIZE = 512000
    DATA_PATH = data_path_dir

    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        did = self.get_argument("id", None)
        dname = self.get_argument("name", None)
        dtype = self.get_argument("type", None)
        dcounter = self.get_argument("counter", "0").zfill(4)
        if dname.split(" ")[0] == "undefined":
            self.finish()
            return
        
        print did, dname, dtype, dcounter 
        if dtype == "left" or dtype == "left-resized" or dtype == "left-resized-mini":
            prefix = "left"
        elif dtype == "top" or dtype == "top-resized" or dtype == "top-resized-mini":
            prefix = "top"
        elif dtype == "front" or dtype == "front-resized" or dtype == "front-resized-mini":
            prefix = "front"
        
        if dtype == "volren":
            self.path = os.path.join(
                self.DATA_PATH,
                dname,
                str(dname)+".jpg")
        elif dtype == "photo":
            self.path = os.path.join(
                self.DATA_PATH,
                dname,
                str(dname)+"_photo.jpg")
        else:
            self.path = os.path.join(
                self.DATA_PATH,
                dname,
                dtype,
                prefix+str(dcounter)+".png")

        #print did, dname, dtype, dcounter
        #print self.path

        self.set_header('Content-Type', 'image/png')
        self.set_header("Content-Length",
                        os.path.getsize(self.path))
        self.flush()
        fd = open(self.path, "rb")
        data = fd.read(self.CHUNK_SIZE)
        while data:
            self.write(data)
            yield tornado.gen.Task(self.flush)
            data = fd.read(self.CHUNK_SIZE)
        fd.close()
        self.finish()


if __name__ == "__main__":
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
