#!/usr/bin/env python

"""
SWIG generation client.  Supports both local and remote generation of SWIG
bindings for multiple languages.
"""

# Future imports
from __future__ import absolute_import
from __future__ import print_function

# Python modules
import argparse
import io
import logging
import os
import socket
import struct
import sys

# LLDB modules
import use_lldb_suite
from lldbsuite.support import fs
from lldbsuite.support import sockutil

# package imports
from . import local
from . import remote

default_ip = "127.0.0.1"
default_port = 8537


def add_subparser_args(parser):
    """Returns options processed from the provided command line.

    @param args the command line to process.
    """

    # A custom action used by the --local command line option.  It can be
    # used with either 0 or 1 argument.  If used with 0 arguments, it
    # searches for a copy of swig located on the physical machine.  If
    # used with 1 argument, the argument is the path to a swig executable.
    class FindLocalSwigAction(argparse.Action):

        def __init__(self, option_strings, dest, **kwargs):
            super(FindLocalSwigAction, self).__init__(
                option_strings, dest, nargs='?', **kwargs)

        def __call__(self, parser, namespace, values, option_string=None):
            swig_exe = None
            if values is None:
                swig_exe = fs.find_executable('swig')
            else:
                swig_exe = values
            setattr(namespace, self.dest, os.path.normpath(swig_exe))

    # A custom action used by the --remote command line option.  It can be
    # used with either 0 or 1 arguments.  If used with 0 arguments it chooses
    # a default connection string.  If used with one argument it is a string
    # of the form `ip_address[:port]`.  If the port is unspecified, the
    # default port is used.
    class RemoteIpAction(argparse.Action):

        def __init__(self, option_strings, dest, **kwargs):
            super(RemoteIpAction, self).__init__(
                option_strings, dest, nargs='?', **kwargs)

        def __call__(self, parser, namespace, values, option_string=None):
            ip_port = None
            if values is None:
                ip_port = (default_ip, default_port)
            else:
                result = values.split(':')
                if len(result) == 1:
                    ip_port = (result[0], default_port)
                elif len(result) == 2:
                    ip_port = (result[0], int(result[1]))
                else:
                    raise ValueError("Invalid connection string")
            setattr(namespace, self.dest, ip_port)

    parser.add_argument(
        "--local",
        action=FindLocalSwigAction,
        dest="swig_executable",
        help=(
            "Run the copy of swig at the specified location, or search PATH"
            "if the location is omitted"))

    parser.add_argument(
        "--remote",
        action=RemoteIpAction,
        help=(
            "Use the given connection string to connect to a remote "
            "generation service"))

    parser.add_argument(
        "--src-root",
        required=True,
        help="The root folder of the LLDB source tree.")

    parser.add_argument(
        "--target-dir",
        default=os.getcwd(),
        help=(
            "Specifies the build dir where the language binding "
            "should be placed"))

    parser.add_argument(
        "--language",
        dest="languages",
        action="append",
        help="Specifies the language to generate bindings for")


def finalize_subparser_options(options):
    if options.languages is None:
        options.languages = ['python']

    if options.remote is None and options.swig_executable is None:
        logging.error("Must specify either --local or --remote")
        sys.exit(-3)

    return options


def establish_remote_connection(ip_port):
    logging.debug("Creating socket...")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    logging.info("Connecting to server {} on port {}"
                 .format(ip_port[0], ip_port[1]))
    s.connect(ip_port)
    logging.info("Connection established...")
    return s


def transmit_request(connection, packed_input):
    logging.info("Sending {} bytes of compressed data."
                 .format(len(packed_input)))
    connection.sendall(struct.pack("!I", len(packed_input)))
    connection.sendall(packed_input)
    logging.info("Awaiting response.")
    response_len = struct.unpack("!I", sockutil.recvall(connection, 4))[0]
    logging.debug("Expecting {} byte response".format(response_len))
    response = sockutil.recvall(connection, response_len)
    return response


def handle_response(options, connection, response):
    logging.debug("Received {} byte response.".format(len(response)))
    logging.debug("Creating output directory {}"
                  .format(options.target_dir))
    os.makedirs(options.target_dir, exist_ok=True)

    logging.info("Unpacking response archive into {}"
                 .format(options.target_dir))
    local.unpack_archive(options.target_dir, response)
    response_file_path = os.path.normpath(
        os.path.join(options.target_dir, "swig_output.json"))
    if not os.path.isfile(response_file_path):
        logging.error("Response file '{}' does not exist."
                      .format(response_file_path))
        return
    try:
        response = remote.deserialize_response_status(
            io.open(response_file_path))
        if response[0] != 0:
            logging.error("An error occurred during generation.  Status={}"
                          .format(response[0]))
            logging.error(response[1])
        else:
            logging.info("SWIG generation successful.")
            if len(response[1]) > 0:
                logging.info(response[1])
    finally:
        os.unlink(response_file_path)


def run(options):
    if options.remote is None:
        logging.info("swig bot client using local swig installation at '{}'"
                     .format(options.swig_executable))
        if not os.path.isfile(options.swig_executable):
            logging.error("Swig executable '{}' does not exist."
                          .format(options.swig_executable))
        config = local.LocalConfig()
        config.languages = options.languages
        config.src_root = options.src_root
        config.target_dir = options.target_dir
        config.swig_executable = options.swig_executable
        local.generate(config)
    else:
        logging.info("swig bot client using remote generation with server '{}'"
                     .format(options.remote))
        connection = None
        try:
            config = remote.generate_config(options.languages)
            logging.debug("Generated config json {}".format(config))
            inputs = [("include/lldb", ".h"),
                      ("include/lldb/API", ".h"),
                      ("scripts", ".swig"),
                      ("scripts/Python", ".swig"),
                      ("scripts/interface", ".i")]
            zip_data = io.BytesIO()
            packed_input = local.pack_archive(
                zip_data, options.src_root, inputs)
            logging.info("(null) -> config.json")
            packed_input.writestr("config.json", config)
            packed_input.close()
            connection = establish_remote_connection(options.remote)
            response = transmit_request(connection, zip_data.getvalue())
            handle_response(options, connection, response)
        finally:
            if connection is not None:
                connection.close()
