import logging
from subprocess import run, PIPE

from module import Module
from utils import break_lines, show_message

__author__ = 'Ion Agorria'

class Smart(Module):
    name = "SMART"

    def __init__(self, modules):
        super().__init__(modules)
        self.update_notified = []

    def run(self):
        """Called at interval, must return number (negative if error)"""
        for device, config_code in self.get_config():
            error = None
            status, firmware, test, code = self.get_smart(device)
            device = device.split(" ")[0]
            if status is None:
                continue
            if status != "Enabled":
                error = "Device %s doesn't have SMART enabled: %s [%s]" % (device, status, code)
            elif test != "PASSED":
                error = "Device %s has test result: %s [%s]" % (device, test, code)
            elif code != int(config_code):
                error = "Device %s returned code %s instead of %s" % (device, code, config_code)
            elif firmware and device not in self.update_notified:
                self.update_notified.append(device)
                text = "Device %s has firmware update [%s]" % (device, code)
                show_message(self.logger, logging.INFO, text)
            if error is not None:
                show_message(self.logger, logging.WARNING, error)

        return 0

    @staticmethod
    def get_smart(device):
        process = run("smartctl -H -i /dev/%s" % device, stdout=PIPE, shell=True)
        result = str(process.stdout, "UTF-8")
        code = process.returncode
        result = break_lines(result)
        line_status = "SMART support is:"
        line_firmware = "A firmware update for this drive may be available"
        line_test = "SMART overall-health self-assessment test result:"

        status = None
        firmware = False
        test = None
        for line in result:
            parts = line.split(" ")
            if line_status in line:
                status = parts[-1]
            if line_firmware in line:
                firmware = True
            if line_test in line:
                test = parts[-1]
        return status, firmware, test, code
