#!/usr/bin/env python

"""
Shared functionality used by `client` and `server` when generating or preparing
to generate SWIG on the local machine.
"""

# Future imports
from __future__ import absolute_import
from __future__ import print_function

# Python modules
import argparse
import imp
import io
import logging
import os
import subprocess
import sys
import tempfile
import zipfile

# LLDB modules
import use_lldb_suite

# Package imports
from lldbsuite.support import fs

class LocalConfig(object):
    src_root = None
    target_dir = None
    languages = None
    swig_executable = None

def pack_archive(bytes_io, src_root, filters):
    logging.info("Creating input file package...")
    zip_file = None
    try:
        # It's possible that a custom-built interpreter will not have the
        # standard zlib module.  If so, we can only store, not compress.  By
        # try to compress since we usually have a standard Python distribution.
        zip_file = zipfile.ZipFile(bytes_io, mode='w',
                                   compression=zipfile.ZIP_DEFLATED)
    except RuntimeError:
        zip_file = zipfile.ZipFile(bytes_io, mode='w',
                                   compression=zipfile.ZIP_STORED)
    archive_entries = []
    if filters is not None:
        def filter_func(t):
            subfolder = t[0]
            ext = t[1]
            full_path = os.path.normpath(os.path.join(src_root, subfolder))
            candidates = [os.path.normpath(os.path.join(full_path, f))
                          for f in os.listdir(full_path)]
            actual = filter(
                lambda f : os.path.isfile(f) and os.path.splitext(f)[1] == ext,
                candidates)
            return (subfolder, map(lambda f : os.path.basename(f), actual))
        archive_entries = map(filter_func, filters)
    else:
        for (root, dirs, files) in os.walk(src_root):
            logging.debug("Adding files {} from directory {} to output package"
                          .format(files, root))
            if len(files) > 0:
                rel_root = os.path.relpath(root, src_root)
                archive_entries.append((rel_root, files))

    archive_entries = list(archive_entries)
    for entry in archive_entries:
        subfolder = entry[0]
        files = list(entry[1])
        for file in files:
            rel_path = os.path.normpath(os.path.join(subfolder, file))
            full_path = os.path.join(src_root, rel_path)
            logging.info("{} -> {}".format(full_path, rel_path))
            zip_file.write(full_path, rel_path)

    return zip_file

def unpack_archive(folder, archive_bytes):
    zip_data = io.BytesIO(archive_bytes)
    logging.debug("Opening zip archive...")
    zip_file = zipfile.ZipFile(zip_data, mode='r')
    zip_file.extractall(folder)
    zip_file.close()

def generate(options):
    include_folder = os.path.join(options.src_root, "include")
    in_file = os.path.join(options.src_root, "scripts", "lldb.swig")
    include_folder = os.path.normcase(include_folder)

    for lang in options.languages:
        lang = lang.lower()
        out_dir = os.path.join(options.target_dir, lang.title())
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)
        out_file = os.path.join(out_dir, "LLDBWrap{}.cpp".format(lang.title()))
        swig_command = [
            options.swig_executable,
            "-c++",
        ]
        swig_command.append("-" + lang)
        if lang == "python":
            swig_command.append("-threads")

        swig_command.extend([
            "-I" + include_folder,
            "-D__STDC_LIMIT_MACROS",
            "-D__STDC_CONSTANT_MACROS",
            "-outdir", out_dir,
            "-o", out_file,
            in_file
        ])

        logging.info("generating swig {} bindings into {}"
                     .format(lang, out_dir))
        logging.debug("swig command line: {}".format(swig_command))
        try:
            # Execute swig
            swig_output = subprocess.check_output(
                swig_command, stderr=subprocess.STDOUT, universal_newlines=True)

            logging.info("swig generation succeeded")
            if swig_output is not None and len(swig_output) > 0:
                logging.info("swig output: %s", swig_output)
            return (0, swig_output)
        except subprocess.CalledProcessError as e:
            logging.error("An error occurred executing swig.  returncode={}"
                          .format(e.returncode))
            logging.error(e.output)
            return (e.returncode, e.output)