# Copyright 2019 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.

# This class contains the basic functionality needed to run any interpreter
# or an interpreter-based tool.

from .common import CMakeException, CMakeConfiguration, CMakeBuildFile
from .. import mlog
from contextlib import contextmanager
from subprocess import Popen, PIPE, TimeoutExpired
from pathlib import Path
import typing as T
import json

if T.TYPE_CHECKING:
    from ..environment import Environment
    from .executor import CMakeExecutor

CMAKE_SERVER_BEGIN_STR = '[== "CMake Server" ==['
CMAKE_SERVER_END_STR = ']== "CMake Server" ==]'

CMAKE_MESSAGE_TYPES = {
    'error': ['cookie', 'errorMessage'],
    'hello': ['supportedProtocolVersions'],
    'message': ['cookie', 'message'],
    'progress': ['cookie'],
    'reply': ['cookie', 'inReplyTo'],
    'signal': ['cookie', 'name'],
}  # type: T.Dict[str, T.List[str]]

CMAKE_REPLY_TYPES = {
    'handshake': [],
    'configure': [],
    'compute': [],
    'cmakeInputs': ['buildFiles', 'cmakeRootDirectory', 'sourceDirectory'],
    'codemodel': ['configurations']
}  # type: T.Dict[str, T.List[str]]

# Base CMake server message classes

class MessageBase:
    def __init__(self, msg_type: str, cookie: str) -> None:
        self.type = msg_type
        self.cookie = cookie

    def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]:
        return {'type': self.type, 'cookie': self.cookie}

    def log(self) -> None:
        mlog.warning('CMake server message of type', mlog.bold(type(self).__name__), 'has no log function')

class RequestBase(MessageBase):
    cookie_counter = 0

    def __init__(self, msg_type: str) -> None:
        super().__init__(msg_type, self.gen_cookie())

    @staticmethod
    def gen_cookie() -> str:
        RequestBase.cookie_counter += 1
        return f'meson_{RequestBase.cookie_counter}'

class ReplyBase(MessageBase):
    def __init__(self, cookie: str, in_reply_to: str) -> None:
        super().__init__('reply', cookie)
        self.in_reply_to = in_reply_to

class SignalBase(MessageBase):
    def __init__(self, cookie: str, signal_name: str) -> None:
        super().__init__('signal', cookie)
        self.signal_name = signal_name

    def log(self) -> None:
        mlog.log(mlog.bold('CMake signal:'), mlog.yellow(self.signal_name))

# Special Message classes

class Error(MessageBase):
    def __init__(self, cookie: str, message: str) -> None:
        super().__init__('error', cookie)
        self.message = message

    def log(self) -> None:
        mlog.error(mlog.bold('CMake server error:'), mlog.red(self.message))

class Message(MessageBase):
    def __init__(self, cookie: str, message: str) -> None:
        super().__init__('message', cookie)
        self.message = message

    def log(self) -> None:
        #mlog.log(mlog.bold('CMake:'), self.message)
        pass

class Progress(MessageBase):
    def __init__(self, cookie: str) -> None:
        super().__init__('progress', cookie)

    def log(self) -> None:
        pass

class MessageHello(MessageBase):
    def __init__(self, supported_protocol_versions: T.List[T.Dict[str, int]]) -> None:
        super().__init__('hello', '')
        self.supported_protocol_versions = supported_protocol_versions

    def supports(self, major: int, minor: T.Optional[int] = None) -> bool:
        for i in self.supported_protocol_versions:
            assert 'major' in i
            assert 'minor' in i
            if major == i['major']:
                if minor is None or minor == i['minor']:
                    return True
        return False

# Request classes

class RequestHandShake(RequestBase):
    def __init__(self, src_dir: Path, build_dir: Path, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None:
        super().__init__('handshake')
        self.src_dir = src_dir
        self.build_dir = build_dir
        self.generator = generator
        self.vers_major = vers_major
        self.vers_minor = vers_minor

    def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]:
        vers = {'major': self.vers_major}
        if self.vers_minor is not None:
            vers['minor'] = self.vers_minor

        # Old CMake versions (3.7) want '/' even on Windows
        self.src_dir   = self.src_dir.resolve()
        self.build_dir = self.build_dir.resolve()

        return {
            **super().to_dict(),
            'sourceDirectory': self.src_dir.as_posix(),
            'buildDirectory': self.build_dir.as_posix(),
            'generator': self.generator,
            'protocolVersion': vers
        }

class RequestConfigure(RequestBase):
    def __init__(self, args: T.Optional[T.List[str]] = None):
        super().__init__('configure')
        self.args = args

    def to_dict(self) -> T.Dict[str, T.Union[str, T.List[str], T.Dict[str, int]]]:
        res = super().to_dict()
        if self.args:
            res['cacheArguments'] = self.args
        return res

class RequestCompute(RequestBase):
    def __init__(self) -> None:
        super().__init__('compute')

class RequestCMakeInputs(RequestBase):
    def __init__(self) -> None:
        super().__init__('cmakeInputs')

class RequestCodeModel(RequestBase):
    def __init__(self) -> None:
        super().__init__('codemodel')

# Reply classes

class ReplyHandShake(ReplyBase):
    def __init__(self, cookie: str) -> None:
        super().__init__(cookie, 'handshake')

class ReplyConfigure(ReplyBase):
    def __init__(self, cookie: str) -> None:
        super().__init__(cookie, 'configure')

class ReplyCompute(ReplyBase):
    def __init__(self, cookie: str) -> None:
        super().__init__(cookie, 'compute')

class ReplyCMakeInputs(ReplyBase):
    def __init__(self, cookie: str, cmake_root: Path, src_dir: Path, build_files: T.List[CMakeBuildFile]) -> None:
        super().__init__(cookie, 'cmakeInputs')
        self.cmake_root = cmake_root
        self.src_dir = src_dir
        self.build_files = build_files

    def log(self) -> None:
        mlog.log('CMake root: ', mlog.bold(self.cmake_root.as_posix()))
        mlog.log('Source dir: ', mlog.bold(self.src_dir.as_posix()))
        mlog.log('Build files:', mlog.bold(str(len(self.build_files))))
        with mlog.nested():
            for i in self.build_files:
                mlog.log(str(i))

class ReplyCodeModel(ReplyBase):
    def __init__(self, data: T.Dict[str, T.Any]) -> None:
        super().__init__(data['cookie'], 'codemodel')
        self.configs = []
        for i in data['configurations']:
            self.configs += [CMakeConfiguration(i)]

    def log(self) -> None:
        mlog.log('CMake code mode:')
        for idx, i in enumerate(self.configs):
            mlog.log(f'Configuration {idx}:')
            with mlog.nested():
                i.log()

# Main client class

class CMakeClient:
    def __init__(self, env: 'Environment') -> None:
        self.env = env
        self.proc = None  # type: T.Optional[Popen]
        self.type_map = {
            'error': lambda data: Error(data['cookie'], data['errorMessage']),
            'hello': lambda data: MessageHello(data['supportedProtocolVersions']),
            'message': lambda data: Message(data['cookie'], data['message']),
            'progress': lambda data: Progress(data['cookie']),
            'reply': self.resolve_type_reply,
            'signal': lambda data: SignalBase(data['cookie'], data['name'])
        }  # type: T.Dict[str, T.Callable[[T.Dict[str, T.Any]], MessageBase]]

        self.reply_map = {
            'handshake': lambda data: ReplyHandShake(data['cookie']),
            'configure': lambda data: ReplyConfigure(data['cookie']),
            'compute': lambda data: ReplyCompute(data['cookie']),
            'cmakeInputs': self.resolve_reply_cmakeInputs,
            'codemodel': lambda data: ReplyCodeModel(data),
        }  # type: T.Dict[str, T.Callable[[T.Dict[str, T.Any]], ReplyBase]]

    def readMessageRaw(self) -> T.Dict[str, T.Any]:
        assert self.proc is not None
        rawData = []
        begin = False
        while self.proc.poll() is None:
            line = self.proc.stdout.readline()
            if not line:
                break
            line = line.decode('utf-8')
            line = line.strip()

            if begin and line == CMAKE_SERVER_END_STR:
                break # End of the message
            elif begin:
                rawData += [line]
            elif line == CMAKE_SERVER_BEGIN_STR:
                begin = True # Begin of the message

        if rawData:
            res = json.loads('\n'.join(rawData))
            assert isinstance(res, dict)
            for i in res.keys():
                assert isinstance(i, str)
            return res
        raise CMakeException('Failed to read data from the CMake server')

    def readMessage(self) -> MessageBase:
        raw_data = self.readMessageRaw()
        if 'type' not in raw_data:
            raise CMakeException('The "type" attribute is missing from the message')
        msg_type = raw_data['type']
        func = self.type_map.get(msg_type, None)
        if not func:
            raise CMakeException(f'Recieved unknown message type "{msg_type}"')
        for i in CMAKE_MESSAGE_TYPES[msg_type]:
            if i not in raw_data:
                raise CMakeException(f'Key "{i}" is missing from CMake server message type {msg_type}')
        return func(raw_data)

    def writeMessage(self, msg: MessageBase) -> None:
        raw_data = '\n{}\n{}\n{}\n'.format(CMAKE_SERVER_BEGIN_STR, json.dumps(msg.to_dict(), indent=2), CMAKE_SERVER_END_STR)
        self.proc.stdin.write(raw_data.encode('ascii'))
        self.proc.stdin.flush()

    def query(self, request: RequestBase) -> MessageBase:
        self.writeMessage(request)
        while True:
            reply = self.readMessage()
            if reply.cookie == request.cookie and reply.type in ['reply', 'error']:
                return reply

            reply.log()

    def query_checked(self, request: RequestBase, message: str) -> MessageBase:
        reply = self.query(request)
        h = mlog.green('SUCCEEDED') if reply.type == 'reply' else mlog.red('FAILED')
        mlog.log(message + ':', h)
        if reply.type != 'reply':
            reply.log()
            raise CMakeException('CMake server query failed')
        return reply

    def do_handshake(self, src_dir: Path, build_dir: Path, generator: str, vers_major: int, vers_minor: T.Optional[int] = None) -> None:
        # CMake prints the hello message on startup
        msg = self.readMessage()
        if not isinstance(msg, MessageHello):
            raise CMakeException('Recieved an unexpected message from the CMake server')

        request = RequestHandShake(src_dir, build_dir, generator, vers_major, vers_minor)
        self.query_checked(request, 'CMake server handshake')

    def resolve_type_reply(self, data: T.Dict[str, T.Any]) -> ReplyBase:
        reply_type = data['inReplyTo']
        func = self.reply_map.get(reply_type, None)
        if not func:
            raise CMakeException(f'Recieved unknown reply type "{reply_type}"')
        for i in ['cookie'] + CMAKE_REPLY_TYPES[reply_type]:
            if i not in data:
                raise CMakeException(f'Key "{i}" is missing from CMake server message type {type}')
        return func(data)

    def resolve_reply_cmakeInputs(self, data: T.Dict[str, T.Any]) -> ReplyCMakeInputs:
        files = []
        for i in data['buildFiles']:
            for j in i['sources']:
                files += [CMakeBuildFile(Path(j), i['isCMake'], i['isTemporary'])]
        return ReplyCMakeInputs(data['cookie'], Path(data['cmakeRootDirectory']), Path(data['sourceDirectory']), files)

    @contextmanager
    def connect(self, cmake_exe: 'CMakeExecutor') -> T.Generator[None, None, None]:
        self.startup(cmake_exe)
        try:
            yield
        finally:
            self.shutdown()

    def startup(self, cmake_exe: 'CMakeExecutor') -> None:
        if self.proc is not None:
            raise CMakeException('The CMake server was already started')
        assert cmake_exe.found()

        mlog.debug('Starting CMake server with CMake', mlog.bold(' '.join(cmake_exe.get_command())), 'version', mlog.cyan(cmake_exe.version()))
        self.proc = Popen(cmake_exe.get_command() + ['-E', 'server', '--experimental', '--debug'], stdin=PIPE, stdout=PIPE)

    def shutdown(self) -> None:
        if self.proc is None:
            return

        mlog.debug('Shutting down the CMake server')

        # Close the pipes to exit
        self.proc.stdin.close()
        self.proc.stdout.close()

        # Wait for CMake to finish
        try:
            self.proc.wait(timeout=2)
        except TimeoutExpired:
            # Terminate CMake if there is a timeout
            # terminate() may throw a platform specific exception if the process has already
            # terminated. This may be the case if there is a race condition (CMake exited after
            # the timeout but before the terminate() call). Additionally, this behavior can
            # also be triggered on cygwin if CMake crashes.
            # See https://github.com/mesonbuild/meson/pull/4969#issuecomment-499413233
            try:
                self.proc.terminate()
            except Exception:
                pass

        self.proc = None
