# Source code for ly.server.main

    # This file is part of python-ly, https://pypi.python.org/pypi/python-ly
    #
    # Copyright (c) 2014 - 2015 by Wilbert Berendsen
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    # See http://www.gnu.org/licenses/ for more information.

    """
    The entry point for the 'ly-server' command.
    """

    from __future__ import unicode_literals
    from __future__ import print_function

    try:
        from http.server import HTTPServer
    except ImportError:
        # Python 2:
        from BaseHTTPServer import HTTPServer

    import copy
    import sys

    import ly.pkginfo
    from . import options
    from . import handler

    def usage():
        """Print usage info."""
        from . import doc
        sys.stdout.write(doc.__doc__)

    def usage_short():
        """Print short usage info."""
        sys.stdout.write("""\
    Usage: ly-server [options]

    An HTTP server for manipulating LilyPond input code

    See ly-server -h for a full list of commands and options.
    """)

    def version():
        """Print version info."""
        sys.stdout.write("ly-server {0}\n".format(ly.pkginfo.version))

    def die(message):
        """Exit with message to STDERR.
        In ly-server this should only be called upon startup, not while processing
        requests. Then the error should be sent back to the client."""
        sys.stderr.write("error: " + message + '\n')
        sys.stderr.write(
            "See ly-server -h for a full list of commands and options.\n")
        sys.exit(1)

    def parse_command_line():
        """Returns a two-tuple(server_opts, cmd_opts)

        server_opts is a ServerOptions instance configuring the server behaviour
        cmd_opts is an Options instance with default options for future command
        executions triggered by HTTP requests.

        Also performs error handling and may exit on certain circumstances.

        """

        if isinstance(sys.argv[0], type('')):
            # python 3 - arguments are unicode strings
            args = iter(sys.argv[1:])
        else:
            # python 2 - arguments are bytes, decode them
            fsenc = sys.getfilesystemencoding() or 'latin1'
            args = (a.decode(fsenc) for a in sys.argv[1:])

        server_opts = options.ServerOptions()
        cmd_opts = options.Options()

        def next_arg(message):
            """Get the next argument, if missing, die with message."""
            try:
                return next(args)
            except StopIteration:
                die(message)

        for arg in args:
            if arg in ('-h', '--help'):
                usage()
                sys.exit(0)
            elif arg in ('-v', '--version'):
                version()
                sys.exit(0)

            # Server Options
            elif arg in ('-p', '--port'):
                server_opts.port = int(next_arg("missing port number"))
            elif arg in ('-t', '--timeout'):
                server_opts.timeout = int(next_arg("missing timeout (in ms)"))

            # Command Options
            elif arg in ('-e', '--encoding'):
                cmd_opts.encoding = next_arg("missing encoding name")
            elif arg == '--output-encoding':
                cmd_opts.output_encoding = next_arg("missing output encoding name")
            elif arg in ('-l', '--language'):
                s = next_arg("missing language name")
                cmd_opts.set_variable("default-language", s)

            # Command configuration Variables
            elif arg == '-d':
                s = next_arg("missing variable=value")
                try:
                    name, value = s.split('=', 1)
                except ValueError:
                    die("missing '=' in variable set")
                cmd_opts.set_variable(name, value)

            elif arg.startswith('-'):
                die('unknown option: ' + arg)

        return server_opts, cmd_opts

    def main():
        server_opts, cmd_opts = parse_command_line()
        handler.default_opts = copy.deepcopy(cmd_opts)
        exit_code = 0
        try:
            server = HTTPServer(('', server_opts.port), handler.RequestHandler)
            print("Welcome to the python-ly HTTP server")
            print("Listening on port {port}".format(port=server_opts.port))
            server.serve_forever()
        except KeyboardInterrupt:
            print("\nKeyboard interrupt received. Shutting down server")
            server.socket.close()
            print("Successfully closed. Bye...")
        return exit_code