# Copyright (c) 2011 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import cgi
import codecs
import datetime
import json
import mimetypes
import os.path
import shutil
import sys
import threading
import time
import wsgiref.handlers

if sys.version_info > (3, 0):
    from http.server import BaseHTTPRequestHandler

else:
    from BaseHTTPServer import BaseHTTPRequestHandler


class ReflectionHandler(BaseHTTPRequestHandler):
    STATIC_FILE_EXTENSIONS = ['.js', '.css', '.html']
    # Subclasses should override.
    STATIC_FILE_DIRECTORY = None

    # Setting this flag to True causes the server to send
    #   Access-Control-Allow-Origin: *
    # with every response.
    allow_cross_origin_requests = False

    def do_GET(self):
        self._handle_request()

    def do_POST(self):
        self._handle_request()

    def do_HEAD(self):
        self._handle_request()

    def read_entity_body(self):
        length = int(self.headers.getheader('content-length'))
        return self.rfile.read(length)

    def _read_entity_body_as_json(self):
        return json.loads(self.read_entity_body())

    def _handle_request(self):
        if "?" in self.path:
            path, query_string = self.path.split("?", 1)
            self.query = cgi.parse_qs(query_string)
        else:
            path = self.path
            self.query = {}
        function_or_file_name = path[1:] or "index.html"

        _, extension = os.path.splitext(function_or_file_name)
        if extension in self.STATIC_FILE_EXTENSIONS:
            self._serve_static_file(function_or_file_name)
            return

        function_name = function_or_file_name.replace(".", "_")
        if not hasattr(self, function_name):
            self.send_error(404, "Unknown function %s" % function_name)
            return
        if function_name[0] == "_":
            self.send_error(401, "Not allowed to invoke private or protected methods")
            return
        function = getattr(self, function_name)
        function()

    def _serve_static_file(self, static_path):
        self._serve_file(os.path.join(self.STATIC_FILE_DIRECTORY, static_path))

    def quitquitquit(self):
        self._serve_text("Server quit.\n")
        # Shutdown has to happen on another thread from the server's thread,
        # otherwise there's a deadlock
        threading.Thread(target=lambda: self.server.shutdown()).start()

    def _send_access_control_header(self):
        if self.allow_cross_origin_requests:
            self.send_header('Access-Control-Allow-Origin', '*')

    def _serve_text(self, text):
        self.send_response(200)
        self._send_access_control_header()
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write(text)

    def _serve_json(self, json_object):
        self.send_response(200)
        self._send_access_control_header()
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        json.dump(json_object, self.wfile)

    def _serve_file(self, file_path, cacheable_seconds=0, headers_only=False):
        if not os.path.exists(file_path):
            self.send_error(404, "File not found")
            return
        with codecs.open(file_path, "rb") as static_file:
            self.send_response(200)
            self._send_access_control_header()
            self.send_header("Content-Length", os.path.getsize(file_path))
            mime_type, encoding = mimetypes.guess_type(file_path)
            if mime_type:
                self.send_header("Content-type", mime_type)

            if cacheable_seconds:
                expires_time = (datetime.datetime.now() +
                    datetime.timedelta(0, cacheable_seconds))
                expires_formatted = wsgiref.handlers.format_date_time(
                    time.mktime(expires_time.timetuple()))
                self.send_header("Expires", expires_formatted)
            self.end_headers()

            if not headers_only:
                shutil.copyfileobj(static_file, self.wfile)
