"""
 analysis_ctrl

 wide are mapping
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2022-01-01
        git sha              : $Format:%H$
        copyright            : (C) 2022 by forschung@ciss.de
        email                : forschung@ciss.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from qgis.core import QgsApplication
from weissflaechenkartierung.src.analysis.analysis_task import *
from weissflaechenkartierung.src.logger import Logger
from PyQt5.QtCore import *
import time


class AnalysisSignals(QObject):
    finished = pyqtSignal(AnalysisResult)   # signal to connect to
    progressChanged = pyqtSignal(float)     # signal to connect to
    error = pyqtSignal(str)              # signal to connect to
    
    
class AnalysisCtrl:
    def __init__(self):
        self._is_running: bool = False
        self.signals = AnalysisSignals()
        self.task: AnalysisTask = None
        self._analysis_last_result = AnalysisResult()
        self._analysis_current_result = AnalysisResult()
        self._task_run_info: AnalysisTaskRunInfo = None
        
    @property
    def last_run_info(self) -> AnalysisResult():
        """
        returns last run information
        """
        return self._task_run_info

    @property
    def last_result_info(self) -> AnalysisResult():
        """
        returns last result information
        """
        return self._analysis_last_result

    @property
    def running(self) -> bool:
        """
        returns the current running state
        """
        return self._is_running
    
    def _update(self):
        """
        sends updates about the task process
        """
        if self.task is not None:
            self.signals.progressChanged.emit(self.task.progress())
            
    def _finished(self):
        """
        called if the analysis task has finished
        """
        Logger.debug("analysis ctrl finished called", )
        self.task = None
        self._analysis_current_result.time_elapsed = time.time() - self._analysis_current_result.time_started
        self._analysis_last_result = self._analysis_current_result
        self.signals.finished.emit(self._analysis_current_result)
        self._is_running = False

    def _result(self, result: AnalysisResult):
        """
        called if the wfk task has results to show
        """
        Logger.debug("analysis ctrl result called", )
        self._analysis_current_result.result = result.result
        self._analysis_current_result.result_txt = result.result_txt
        self._analysis_current_result.layer_to_protocol = result.layer_to_protocol

    def stop(self) -> None:
        """
        called if to stop the wfk process
        """
        if self.task is not None:
            try:
                self.task.cancel()
            except Exception as e:
                self.signals.error.emit("Can not cancel analysis task")
            self._is_running = False
            self.task = None
            self.signals.finished.emit(self._analysis_current_result)        # emit the watcher, the task finished

    def start(self, analysis_data: AnalysisTaskRunInfo):
        """
        starts the wfk process
        """
        Logger.debug("Check given analysis data", )
        if len(analysis_data.layer_list) == 0:
            self.signals.error.emit("There are no layers left to analyse")
            self.signals.finished.emit(self._analysis_current_result)  # emit the watcher, the task finished
            return

        if not analysis_data.description:
            self.signals.error.emit("The given Task has no description!")
            self.signals.finished.emit(self._analysis_current_result)  # emit the watcher, the task finished
            return
        Logger.debug("RunWithError: " + str(analysis_data.run_with_errors), )
        Logger.debug("Layers to analyze: " + str(len(analysis_data.layer_list)), )

        Logger.debug("Run analysis process", )
        self._start(analysis_data)

    def _start(self, analysis_data: AnalysisTaskRunInfo):
        """
        starts the wfk process
        """
        self._task_run_info = analysis_data
        self.task = AnalysisTask(run_config=analysis_data)
        self.task.signals.finished.connect(self._finished)
        self.task.signals.result.connect(self._result)
        self.task.progressChanged.connect(lambda: self._update())
        self._is_running = True
        QgsApplication.taskManager().addTask(self.task)     # start wfk task
        self._analysis_current_result.time_started = time.time()     # track start time
