import BaseHTTPServer
import jinja2
import json
import os
import time

from urlparse import parse_qs

from client import TweetClient
from status_tracker import config_parser
from status_tracker import data_analyzer
from status_tracker import db
from status_tracker import utils

CONFIGS = config_parser.Config().get_config()


HOSTNAME = CONFIGS['server.host']
PORT = int(CONFIGS['server.port'])
TEMPLATE_FOLDER = CONFIGS['files.template_folder']


class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_headers(200, 'text/html')

    def do_GET(self):
        if self.path.startswith('/api/report'):
            query = parse_qs(self.path)['/api/report?query'][0]
            self.send_headers(200, 'text/html')
            template = generate_report(query)
            self.wfile.write(template.encode('utf-8'))

        elif self.path.startswith('/images'):
            filename = self.path.split('/').pop()
            self.send_static_files(filename, 'images', 'image/png')

        elif self.path.startswith('/css'):
            filename = self.path.split('/').pop()
            self.send_static_files(filename, 'css', 'text/css')

        elif self.path.startswith('/js'):
            filename = self.path.split('/').pop()
            self.send_static_files(filename, 'js', 'application/javascript')

        elif self.path.startswith('/reports'):
            self.send_headers(200, 'text/html')
            with open(os.path.join(TEMPLATE_FOLDER,
                      'reports.html')) as fp:
                self.wfile.write(fp.read())

        elif self.path.startswith('/') or self.startswith('/tweet_fetch'):
            self.send_headers(200, 'text/html')
            with open(os.path.join(TEMPLATE_FOLDER,
                      'tweets_fetch.html')) as fp:
                self.wfile.write(fp.read())

    def do_POST(self):
        if self.path == '/api/tweet':
            content_length = int(self.headers['Content-Length'])
            data = json.loads(self.rfile.read(content_length))
            for tweet in utils.chunker(data['tweets'], 10):
                db.insert_tweet(tweet, data['search_query'])

        elif self.path.startswith('/api/tweet_via_query'):
            content_length = int(self.headers['Content-Length'])
            query = parse_qs(self.rfile.read(content_length))['query'][0]

            tweet_client = TweetClient(query)
            tweets = tweet_client.get_tweets()
            for tweet in utils.chunker(tweets['tweets'], 10):
                db.insert_tweet(tweet, tweets['search_query'])

        self.send_headers(200, 'text/html')
        with open(os.path.join(TEMPLATE_FOLDER, 'success.html'), 'rb') as fp:
            self.wfile.write(fp.read())

    def send_static_files(self, filename, file_type, content_type):
        """This method is a wrapper for serving static files.

        This method takes few parameters, which define content which needs to
        be sent to the client.

        :Parameters:
            - `filename`: name of the file to send to client,
            - `file_type`: type of the file to send,
            - `content_type`: content-type of the file's content.
        """
        filepath = os.path.join(os.environ['STATICROOT'], file_type,
                                filename)
        self.send_headers(200, content_type, os.path.getsize(filepath))

        with open(filepath, 'rb') as fp:
            self.wfile.write(fp.read())

    def send_headers(self, status, content_type, content_length=0):
        """This method is a wrapper for sending http headers.

        This method takes few parameters which define header in http response
        and sends them.

        :Parameters:
            - `status`: status of the http response,
            - `content_type`: content type of the http response,
            - `content_length`: content length.
        """
        self.send_response(status)
        self.send_header('Content-Type', content_type)
        if content_length:
            self.send_header('Content-Length', content_length)
        self.end_headers()


def generate_report(search_query):
    """Generates report template and returnes it.

    This function generates report template and returnes it.

    :Parameters:
        - `search_query`: query to generate report to.

    :Returnes:
        string with generated template.
    """
    analyser = data_analyzer.TweetAnalyser(search_query)
    context = analyser.analyse()

    with open(os.path.join(TEMPLATE_FOLDER,
                           'report_template.html'), 'r') as fp:
        report_tmpl = jinja2.Template(fp.read())

    return report_tmpl.render(context)


if __name__ == '__main__':
    server = BaseHTTPServer.HTTPServer((HOSTNAME, PORT), RequestHandler)
    print time.asctime(), 'Server Starts - %s:%s' % (HOSTNAME, PORT)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    server.server_close()
    print time.asctime(), 'Server Stops - %s:%s' % (HOSTNAME, PORT)
