#!/usr/bin/env python

"""
:author: Vladan S
:copyright: D-Logic   http://www.d-logic.net
 
"""

__program_version = '4.0.7.16 '

"""
 
"""

import cgi
import posixpath
import shutil
import traceback
import urllib
import urllib2
import StringIO
import threading
import urlparse

from commands import *
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
from SocketServer import ThreadingMixIn
from mimetypes import types_map
from socket import *
from constants import *
from shell import device_list
from shell.ais_shell import AIS_HTTP, list_device


def AisHttpGetProgramVersion():
    return 'App name  : {0}  : {1}'.format(AIS_HTTP, __program_version)


def http_request(path, post_attrib, time_out=20):
    try:
        req = urllib2.Request(path, post_attrib)
        req.add_header("Content-type", "application/x-www-form-urlencoded")
        page = urllib2.urlopen(req, timeout=time_out)
        return page.read(), page.code
    except urllib2.URLError, urlExc:
        return '', urlExc.reason
    except urllib2.HTTPError, httpExc:
        return '', httpExc.code


class GetHandler(BaseHTTPRequestHandler):
    # global url_query

    def WriteFile(self, path):
        '''Write any file to client
           :param path: self.path-> path to the file 
        '''
        if self.path == '/':
            self.path = path
        fname, ext = os.path.splitext(self.path)
        fname = self.path.lstrip("/")
        with open(os.path.join(os.sep, fname)) as t:
            self.send_response(200)
            self.send_header('Content-type', types_map[ext])
            self.end_headers()
            self.wfile.write(t.read())
            t.close()
        return

    def list_dir(self, path):
        try:
            listdirs = os.listdir(path)
        except os.error:
            self.send_error(404)
            return None
        f = StringIO.StringIO()
        f.write('<!DOCTYPE html>')
        f.write("<html>\n<title>Directory listing</title>\n")
        f.write("<body>\n<h2>Directory listing for {0}</h2>\n".format(path))
        f.write("<hr>\n<ul>\n")
        for name in listdirs:
            fullname = os.path.join(path, name)
            displayname = linkname = name
            if os.path.isdir(fullname):
                displayname = name + "/"
                linkname = name + "/"
            if os.path.islink(fullname):
                displayname = name + "@"
            f.write('<li><a href="%s">%s</a>\n' % (urllib.quote(linkname), cgi.escape(displayname)))
        f.write("</ul>\n<hr>\n</body>\n</html>\n")
        length = f.tell()
        f.seek(0)
        self.send_response(200)
        encoding = sys.getfilesystemencoding()
        self.send_header("Content-type", "text/html; charset=%s" % encoding)
        self.send_header("Content-Length", str(length))
        self.end_headers()
        return f

    def do_HEAD(self):
        f = self.send_head()
        if f:
            f.close()

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.
           :param path:current path to translate path
           :return: translated path
        """

        path = path.split('?', 1)[0]
        path = path.split('#', 1)[0]
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = os.getcwd()
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)
        return path

    def script_name(self):
        if not os.path.basename(sys.argv[0]) == AIS_HTTP:
            return [HTML_OTHER_INIT_SCRIPT, HTM_OTHER_INIT_SCRIPT]
        return [HTML_INIT_SCRIPT, HTM_INIT_SCRIPT]

    def send_head(self):
        try:
            path = self.translate_path(self.path)
            f = None
            if os.path.isdir(path):
                scripts = self.script_name()
                for index in scripts:
                    index = os.path.join(os.path.join(os.getcwd(), HTML_FOLDER, index))
                    if os.path.exists(index):
                        path = index
                        break
                else:
                    return self.list_dir(path)
            try:
                f = open(path, 'rb')
            except IOError:
                self.send_error(404, 'File Not Found: %s' % self.path)
                return None

            fname, ext = os.path.splitext(path)
            self.send_response(200)
            self.send_header("Content-type", types_map[ext])
            fs = os.fstat(f.fileno())
            self.send_header("Content-Length", str(fs[6]))
            self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
            self.end_headers()
            return f
        except IOError:
            self.send_error(404, 'File Not Found: %s' % self.path)
        return None

    def SetHeaders(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.end_headers()

    def SetHeadersHtml(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()


    def do_GET(self):
        try:
            f = self.send_head()
            if f:
                shutil.copyfileobj(f, self.wfile)
                f.close()
        except IOError:
            self.send_error(404, 'File Not Found: %s' % self.path)
        return

    def do_POST(self):
        try:
            global url_query
            ldev = device_list.S_DEVICE
            ctype, pdict = cgi.parse_header(self.headers['content-type'])

            if ctype == 'multipart/form-data':
                pq = cgi.parse_multipart(self.rfile, pdict)

            elif ctype == 'application/x-www-form-urlencoded':
                length = int(self.headers['content-length'])
                # pq = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
                pq = urlparse.parse_qs(self.rfile.read(length), keep_blank_values=1)

            else:
                pq = {}

            f = ''.join(pq[FUNCTION] if pq.get(FUNCTION) else '')
            device = ''.join(pq[DEVICE] if pq.get(DEVICE) else '')

            try:
                if device is '':
                    ldev.hnd = HND_LIST[0]
                elif int(device) > len(HND_LIST):
                    self.wfile.write("\ndev[%s]NO DEVICE FOUND (or resource busy)\n" % device)
                    return
                else:
                    ldev.hnd = HND_LIST[int(device, 10) - 1]
            except Exception as exc:
                print exc

            getcommand = command(f, ldev, **pq)
            if getcommand:
                self.SetHeaders()
                self.wfile.write(getcommand)
                return
            else:
                if not os.path.basename(sys.argv[0]) == AIS_HTTP:
                    try:
                        from dopostprocess import procommands
                        from ais_readers_main_process import GetOpenAisHtml
                        content = GetOpenAisHtml(**pq)
                        if content:
                            return self.WriteFile(content)
                        content = procommands(f, ldev, **pq)
                        if content:
                            self.SetHeaders()
                            self.wfile.write(content)
                        else:
                            return ''
                    except Exception as exc:
                        print traceback.print_exc()

        except Exception as error_mess:
            self.wfile.write(traceback.print_exc())




class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""


def RunAll():
    serv = threading.Thread(target=handler_server)
    serv.start()
    while True:
        try:
            if serv.isAlive():
                serv.join(timeout=SERV_JOIN)
        except (KeyboardInterrupt, SystemExit, Exception) as e:
            httpd.server_close()
            print '\nServer stopped\nProgram close', e
            shut_event.set()
            if sys.platform.startswith('linux'):
                os.system('pkill -9 python')
            elif sys.platform.startswith('win'):
                sys.exit(0)
            break


def handler_server():
    global httpd
    while not shut_event.is_set():
        my_lock.acquire()
        httpd.handle_request()
        my_lock.release()
        time.sleep(THD_SLEEP)


def init():
    print AISGetLibraryVersionStr()
    global httpd
    list_device()
    httpd = HTTPServer((HTTP_SERVER_NAME, HTTP_SERVER_PORT), GetHandler)
    httpd.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    RunAll()


my_lock = threading.Lock()
shut_event = threading.Event()

if __name__ == '__main__':
    global httpd
    init()