#
# Aura Engine
#
# Copyright (C) 2020    David Trattnig <david.trattnig@subsquare.at>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import urllib
import logging
import os.path
from os import path

from modules.communication.redis.adapter import ClientRedisAdapter


class Monitoring:
    """
    Engine Monitoring
    """
    logger = None
    soundsystem = None
    status = None


    def __init__(self, config, soundsystem):
        """
        Initialize Monitoring
        """
        self.logger = logging.getLogger("AuraEngine")
        self.config = config
        self.soundsystem = soundsystem
        self.status = dict()
        self.status["soundsystem"] = dict()



    def update_status(self):
        """
        Requests the current status of all components
        """
        self.status["soundsystem"]["mixer"] = self.soundsystem.get_mixer_status()
        #self.status["soundsystem"]["recorder"] = self.soundsystem.get_recorder_status()
        self.status["redis_ready"] = self.validate_redis_connection()
        self.status["api_steering_ready"] = self.validate_url_connection(self.config.get("api_steering_status"))
        self.status["api_tank_ready"] = self.validate_url_connection(self.config.get("api_tank_status"))
        self.status["audio_store"] = self.validate_directory(self.config.get("audiofolder"))

        # Set overall status
        if self.has_valid_status():
            self.status["engine_status"] = "OK"
        else:
            self.status["engine_status"] = "INVALID"



    def get_status(self):
        """
        Retrieves the current monitoring status.
        """
        self.update_status()
        return self.status



    def has_valid_status(self):
        """
        Checks if the current status is valid to run engine
        """
        try:
            if self.status["soundsystem"]["mixer"]["in_filesystem_0"] \
                and self.status["redis_ready"] \
                and self.status["audio_store"]["exists"]:

                return True
            return False
        except Exception as e:
            self.logger.error("Exception while validating engine status: " + str(e))
            return False


    def validate_url_connection(self, url):
        """
        Checks if connection to passed URL is successful.
        """
        try:
            request = urllib.request.Request(url)
            response = urllib.request.urlopen(request)
            response.read()
        except Exception:
            return False

        return True



    def validate_redis_connection(self):
        """
        Checks if the connection to Redis is successful.
        """
        try:
            cra = ClientRedisAdapter(self.config)
            cra.publish("aura", "status")
        except:
            return False

        return True



    def validate_directory(self, dir_path):
        """
        Checks if a given directory is existing and holds content
        """
        status = dict()
        status["exists"] = path.exists(dir_path) and os.path.isdir(dir_path)
        status["has_content"] = False

        if status["exists"]:
            status["has_content"] = any([True for _ in os.scandir(dir_path)])

        return status