# Copyright 2013-2014 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import io
import sys
import time
import platform
from contextlib import contextmanager

"""This is (mostly) a standalone module used to write logging
information about Meson runs. Some output goes to screen,
some to logging dir and some goes to both."""

def _windows_ansi():
    from ctypes import windll, byref
    from ctypes.wintypes import DWORD

    kernel = windll.kernel32
    stdout = kernel.GetStdHandle(-11)
    mode = DWORD()
    if not kernel.GetConsoleMode(stdout, byref(mode)):
        return False
    # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4
    # If the call to enable VT processing fails (returns 0), we fallback to
    # original behavior
    return kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')

if platform.system().lower() == 'windows':
    colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()
else:
    colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
log_dir = None
log_file = None
log_fname = 'meson-log.txt'
log_depth = 0
log_timestamp_start = None
log_fatal_warnings = False

def initialize(logdir, fatal_warnings=False):
    global log_dir, log_file, log_fatal_warnings
    log_dir = logdir
    log_file = open(os.path.join(logdir, log_fname), 'w', encoding='utf8')
    log_fatal_warnings = fatal_warnings

def set_timestamp_start(start):
    global log_timestamp_start
    log_timestamp_start = start

def shutdown():
    global log_file
    if log_file is not None:
        path = log_file.name
        exception_around_goer = log_file
        log_file = None
        exception_around_goer.close()
        return path
    return None

class AnsiDecorator:
    plain_code = "\033[0m"

    def __init__(self, text, code, quoted=False):
        self.text = text
        self.code = code
        self.quoted = quoted

    def get_text(self, with_codes):
        text = self.text
        if with_codes:
            text = self.code + self.text + AnsiDecorator.plain_code
        if self.quoted:
            text = '"{}"'.format(text)
        return text

def bold(text, quoted=False):
    return AnsiDecorator(text, "\033[1m", quoted=quoted)

def red(text):
    return AnsiDecorator(text, "\033[1;31m")

def green(text):
    return AnsiDecorator(text, "\033[1;32m")

def yellow(text):
    return AnsiDecorator(text, "\033[1;33m")

def blue(text):
    return AnsiDecorator(text, "\033[1;34m")

def cyan(text):
    return AnsiDecorator(text, "\033[1;36m")

def process_markup(args, keep):
    arr = []
    if log_timestamp_start is not None:
        arr = ['[{:.3f}]'.format(time.monotonic() - log_timestamp_start)]
    for arg in args:
        if arg is None:
            continue
        if isinstance(arg, str):
            arr.append(arg)
        elif isinstance(arg, AnsiDecorator):
            arr.append(arg.get_text(keep))
        else:
            arr.append(str(arg))
    return arr

def force_print(*args, **kwargs):
    iostr = io.StringIO()
    kwargs['file'] = iostr
    print(*args, **kwargs)

    raw = iostr.getvalue()
    if log_depth > 0:
        prepend = '|' * log_depth
        raw = prepend + raw.replace('\n', '\n' + prepend, raw.count('\n') - 1)

    # _Something_ is going to get printed.
    try:
        print(raw, end='')
    except UnicodeEncodeError:
        cleaned = raw.encode('ascii', 'replace').decode('ascii')
        print(cleaned, end='')

def debug(*args, **kwargs):
    arr = process_markup(args, False)
    if log_file is not None:
        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.
        log_file.flush()

def log(*args, **kwargs):
    arr = process_markup(args, False)
    if log_file is not None:
        print(*arr, file=log_file, **kwargs) # Log file never gets ANSI codes.
        log_file.flush()
    if colorize_console:
        arr = process_markup(args, True)
    force_print(*arr, **kwargs)

def _log_error(severity, *args, **kwargs):
    from .mesonlib import get_error_location_string
    from .environment import build_filename
    from .mesonlib import MesonException
    if severity == 'warning':
        args = (yellow('WARNING:'),) + args
    elif severity == 'error':
        args = (red('ERROR:'),) + args
    elif severity == 'deprecation':
        args = (red('DEPRECATION:'),) + args
    else:
        assert False, 'Invalid severity ' + severity

    location = kwargs.pop('location', None)
    if location is not None:
        location_file = os.path.join(location.subdir, build_filename)
        location_str = get_error_location_string(location_file, location.lineno)
        args = (location_str,) + args

    log(*args, **kwargs)

    global log_fatal_warnings
    if log_fatal_warnings:
        raise MesonException("Fatal warnings enabled, aborting")

def error(*args, **kwargs):
    return _log_error('error', *args, **kwargs)

def warning(*args, **kwargs):
    return _log_error('warning', *args, **kwargs)

def deprecation(*args, **kwargs):
    return _log_error('deprecation', *args, **kwargs)

def exception(e):
    log()
    if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'):
        log('%s:%d:%d:' % (e.file, e.lineno, e.colno), red('ERROR: '), e)
    else:
        log(red('ERROR:'), e)

# Format a list for logging purposes as a string. It separates
# all but the last item with commas, and the last with 'and'.
def format_list(list):
    l = len(list)
    if l > 2:
        return ' and '.join([', '.join(list[:-1]), list[-1]])
    elif l == 2:
        return ' and '.join(list)
    elif l == 1:
        return list[0]
    else:
        return ''

@contextmanager
def nested():
    global log_depth
    log_depth += 1
    try:
        yield
    finally:
        log_depth -= 1
