# Copyright (c) Mengning Software. 2023. All rights reserved.
#
# Super IDE licensed under GNU Affero General Public License v3 (AGPL-3.0) .
# You can use this software according to the terms and conditions of the AGPL-3.0.
# You may obtain a copy of AGPL-3.0 at:
#
#    https://www.gnu.org/licenses/agpl-3.0.txt
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the AGPL-3.0 for more details.

import time
from pathlib import Path

# from ajsonrpc.core import JSONRPC20DispatchException

from superide.compat import aio_get_running_loop
from superide.home.rpc.handlers.base import BaseRPCHandler


class IDERPC():
    COMMAND_TIMEOUT = 1.5  # in seconds

    def __init__(self):
        self._ide_queue = []
        self._cmd_queue = {}

    async def listen_commands(self):
        f = aio_get_running_loop().create_future()
        self._ide_queue.append(f)
        self._process_commands()
        return await f

    async def send_command(self, command, params=None):
        cmd_id = f"ide-{command}-{time.time()}"
        self._cmd_queue[cmd_id] = {
            "method": command,
            "params": params,
            "time": time.time(),
            "future": aio_get_running_loop().create_future(),
        }
        self._process_commands()
        # in case if IDE agent has not been started
        aio_get_running_loop().call_later(
            self.COMMAND_TIMEOUT + 0.1, self._process_commands
        )
        return await self._cmd_queue[cmd_id]["future"]

    def on_command_result(self, cmd_id, value):
        if cmd_id not in self._cmd_queue:
            return False
        if self._cmd_queue[cmd_id]["method"] == "get_pio_project_dirs":
            value = [str(Path(p).resolve()) for p in value]
        self._cmd_queue[cmd_id]["future"].set_result(value)
        del self._cmd_queue[cmd_id]
        return True

    def _process_commands(self):
        for cmd_id in list(self._cmd_queue):
            cmd_data = self._cmd_queue[cmd_id]
            if cmd_data["future"].done():
                del self._cmd_queue[cmd_id]
                continue

            if (
                not self._ide_queue
                and (time.time() - cmd_data["time"]) > self.COMMAND_TIMEOUT
            ):
                cmd_data["future"].set_exception(
                    JSONRPC20DispatchException(
                        code=4005, message="PIO Home IDE agent is not started"
                    )
                )
                continue

            while self._ide_queue:
                self._ide_queue.pop().set_result(
                    {
                        "id": cmd_id,
                        "method": cmd_data["method"],
                        "params": cmd_data["params"],
                    }
                )
