#!/usr/bin/env python2

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import common
import sys, os, shutil, optparse, logging
import six

from autotest_lib.client.common_lib import error, utils
from autotest_lib.client.common_lib import logging_config, logging_manager


"""
Compile All Autotest GWT Clients Living in autotest/frontend/client/src
"""



_AUTOTEST_DIR = common.autotest_dir
_DEFAULT_GWT_DIRS = ['/usr/local/lib/gwt', '/opt/google-web-toolkit']
_DEFAULT_APP_DIR = os.path.join(_AUTOTEST_DIR, 'frontend/client')
_DEFAULT_INSTALL_DIR = os.path.join(_DEFAULT_APP_DIR, 'www')
_TMP_COMPILE_DIR = _DEFAULT_INSTALL_DIR + '.new'

_COMPILE_LINE = ('java  -Xmx512M %(extra_args)s '
                 '-cp "%(app_dir)s/src:%(app_dir)s/bin:%(gwt_dir)s/gwt-user.jar'
                 ':%(gwt_dir)s/gwt-dev.jar" -Djava.awt.headless=true '
                 'com.google.gwt.dev.Compiler -war "%(compile_dir)s" '
                 '%(project_client)s')

class CompileClientsLoggingConfig(logging_config.LoggingConfig):
    def configure_logging(self, results_dir=None, verbose=False):
        super(CompileClientsLoggingConfig, self).configure_logging(
                                                               use_console=True,
                                                               verbose=verbose)

def enumerate_projects():
    """List projects in _DEFAULT_APP_DIR."""
    src_path = os.path.join(_DEFAULT_APP_DIR, 'src')
    projects = {}
    for project in os.listdir(src_path):
        projects[project] = []
        project_path = os.path.join(src_path, project)
        for file in os.listdir(project_path):
            if file.endswith('.gwt.xml'):
                projects[project].append(file[:-8])
    return projects


def find_gwt_dir():
    """See if GWT is installed in site-packages or in the system,
       site-packages is favored over a system install or a /usr/local install.
    """
    site_gwt = os.path.join(_AUTOTEST_DIR, 'site-packages', 'gwt')
    gwt_dirs = [site_gwt] + _DEFAULT_GWT_DIRS

    for gwt_dir in gwt_dirs:
        if os.path.isdir(gwt_dir):
            return gwt_dir
    logging.error('Unable to find GWT. '
                  'You can use utils/build_externals.py to install it.')
    sys.exit(1)


def install_completed_client(compiled_dir, project_client):
    """Remove old client directory if it exists,  move installed client to the
       old directory and move newly compield client to the installed client
       dir.
       @param compiled_dir: Where the new client was compiled
       @param project_client: project.client pair e.g. autotest.AfeClient
       @returns True if installation was successful or False if it failed
    """
    tmp_client_dir = os.path.join(_TMP_COMPILE_DIR, project_client)
    install_dir = os.path.join(_DEFAULT_INSTALL_DIR, project_client)
    old_install_dir = os.path.join(_DEFAULT_INSTALL_DIR,
                                   project_client + '.old')
    if not os.path.exists(_DEFAULT_INSTALL_DIR):
        os.mkdir(_DEFAULT_INSTALL_DIR)

    if os.path.isdir(tmp_client_dir):
        if os.path.isdir(old_install_dir):
            shutil.rmtree(old_install_dir)
        if os.path.isdir(install_dir):
            os.rename(install_dir, old_install_dir)
        try:
            os.rename(tmp_client_dir, install_dir)
            return True
        except Exception as err:
            # If we can't rename the client raise an exception
            # and put the old client back
            shutil.rmtree(install_dir)
            shutil.copytree(old_install_dir, install_dir)
            logging.error('Copying old client: %s', err)
    else:
        logging.error('Compiled directory is gone, something went wrong')

    return False


def compile_and_install_client(project_client, extra_args='',
                               install_client=True):
    """Compile the client into a temporary directory, if successful
       call install_completed_client to install the new client.
       @param project_client: project.client pair e.g. autotest.AfeClient
       @param install_client: Boolean, if True install the clients
       @return True if install and compile was successful False if it failed
    """
    java_args = {}
    java_args['compile_dir'] = _TMP_COMPILE_DIR
    java_args['app_dir'] = _DEFAULT_APP_DIR
    java_args['gwt_dir'] = find_gwt_dir()
    java_args['extra_args'] = extra_args
    java_args['project_client'] = project_client
    cmd = _COMPILE_LINE % java_args

    logging.info('Compiling client %s', project_client)
    try:
        utils.run(cmd, verbose=True)
        if install_client:
            return install_completed_client(java_args['compile_dir'],
                                            project_client)
        return True
    except error.CmdError:
        logging.error('Error compiling %s, leaving old client', project_client)

    return False


def compile_all_projects(extra_args=''):
    """Compile all projects available as defined by enumerate_projects.
       @returns list of failed client installations
    """
    failed_clients = []
    for project,clients in six.iteritems(enumerate_projects()):
        for client in clients:
            project_client = '%s.%s' % (project, client)
            if not compile_and_install_client(project_client, extra_args):
                failed_clients.append(project_client)

    return failed_clients


def print_projects():
    logging.info('Projects that can be compiled:')
    for project,clients in six.iteritems(enumerate_projects()):
        for client in clients:
            logging.info('%s.%s', project, client)


def main():
    logging_manager.configure_logging(CompileClientsLoggingConfig(),
                                      verbose=True)
    parser = optparse.OptionParser()
    parser.add_option('-l', '--list-projects',
                      action='store_true', dest='list_projects',
                      default=False,
                      help='List all projects and clients that can be compiled')
    parser.add_option('-a', '--compile-all',
                      action='store_true', dest='compile_all',
                     default=False,
                     help='Compile all available projects and clients')
    parser.add_option('-c', '--compile',
                      dest='compile_list', action='store',
                      help='List of clients to compiled (e.g. -c "x.X c.C")')
    parser.add_option('-e', '--extra-args',
                      dest='extra_args', action='store',
                      default='',
                      help='Extra arguments to pass to java')
    parser.add_option('-d', '--no-install', dest='install_client',
                      action='store_false', default=True,
                      help='Do not install the clients just compile them')
    options, args = parser.parse_args()

    if len(sys.argv) < 2:
        parser.print_help()
        sys.exit(0)
    elif options.list_projects:
        print_projects()
        sys.exit(0)
    elif options.compile_all and options.compile_list:
        logging.error('Options -c and -a are mutually exclusive')
        parser.print_help()
        sys.exit(1)

    failed_clients = []
    if options.compile_all:
        failed_clients = compile_all_projects(options.extra_args)
    elif options.compile_list:
        for client in options.compile_list.split():
            if not compile_and_install_client(client, options.extra_args,
                                              options.install_client):
                failed_clients.append(client)

    if os.path.exists(_TMP_COMPILE_DIR):
        shutil.rmtree(_TMP_COMPILE_DIR)

    if failed_clients:
        logging.error('The following clients failed: %s',
                      '\n'.join(failed_clients))
        sys.exit(1)


if __name__ == '__main__':
    main()
