# SPDX-License-Identifier: Apache-2.0
# Copyright 2018 The Meson development team

# This file contains the detection logic for external dependencies that
# are UI-related.
from __future__ import annotations

import json
import os

from . import ExtensionModule, ModuleInfo
from .. import mlog
from ..dependencies import Dependency
from ..dependencies.dub import DubDependency
from ..interpreterbase import typed_pos_args
from ..mesonlib import Popen_safe, MesonException, listify

class DlangModule(ExtensionModule):
    class_dubbin = None
    init_dub = False

    INFO = ModuleInfo('dlang', '0.48.0')

    def __init__(self, interpreter):
        super().__init__(interpreter)
        self.methods.update({
            'generate_dub_file': self.generate_dub_file,
        })

    def _init_dub(self, state):
        if DlangModule.class_dubbin is None:
            self.dubbin = DubDependency.class_dubbin
            DlangModule.class_dubbin = self.dubbin
        else:
            self.dubbin = DlangModule.class_dubbin

        if DlangModule.class_dubbin is None:
            self.dubbin = self.check_dub(state)
            DlangModule.class_dubbin = self.dubbin
        else:
            self.dubbin = DlangModule.class_dubbin

        if not self.dubbin:
            if not self.dubbin:
                raise MesonException('DUB not found.')

    @typed_pos_args('dlang.generate_dub_file', str, str)
    def generate_dub_file(self, state, args, kwargs):
        if not DlangModule.init_dub:
            self._init_dub(state)

        config = {
            'name': args[0]
        }

        config_path = os.path.join(args[1], 'dub.json')
        if os.path.exists(config_path):
            with open(config_path, encoding='utf-8') as ofile:
                try:
                    config = json.load(ofile)
                except ValueError:
                    mlog.warning('Failed to load the data in dub.json')

        warn_publishing = ['description', 'license']
        for arg in warn_publishing:
            if arg not in kwargs and \
               arg not in config:
                mlog.warning('Without', mlog.bold(arg), 'the DUB package can\'t be published')

        for key, value in kwargs.items():
            if key == 'dependencies':
                values = listify(value, flatten=False)
                config[key] = {}
                for dep in values:
                    if isinstance(dep, Dependency):
                        name = dep.get_name()
                        ret, res = self._call_dubbin(['describe', name])
                        if ret == 0:
                            version = dep.get_version()
                            if version is None:
                                config[key][name] = ''
                            else:
                                config[key][name] = version
            else:
                config[key] = value

        with open(config_path, 'w', encoding='utf-8') as ofile:
            ofile.write(json.dumps(config, indent=4, ensure_ascii=False))

    def _call_dubbin(self, args, env=None):
        p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2]
        return p.returncode, out.strip()

    def check_dub(self, state):
        dubbin = state.find_program('dub', silent=True)
        if dubbin.found():
            try:
                p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
                if p.returncode != 0:
                    mlog.warning('Found dub {!r} but couldn\'t run it'
                                 ''.format(' '.join(dubbin.get_command())))
                    # Set to False instead of None to signify that we've already
                    # searched for it and not found it
                    dubbin = False
            except (FileNotFoundError, PermissionError):
                dubbin = False
        else:
            dubbin = False
        if dubbin:
            mlog.log('Found DUB:', mlog.bold(dubbin.get_path()),
                     '(%s)' % out.strip())
        else:
            mlog.log('Found DUB:', mlog.red('NO'))
        return dubbin

def initialize(*args, **kwargs):
    return DlangModule(*args, **kwargs)
