"""
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 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 General Public License for more details.


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

Copyright © 2019 Cloud Linux Software Inc.

This software is also available under ImunifyAV commercial license,
see <https://www.imunify360.com/legal/eula>
"""
import os


class ScanFailedError(Exception):
    def __init__(
        self,
        *,
        message,
        command,
        return_code,
        out,
        err,
        scan_id,
        path,
    ):
        """
        In some scanners out and errors can be lists of bytes or bytes, we will
        convert all to string
        :param message:
        :param command:
        :param return_code:
        :param out:
        :param err:
        """
        self.message = message
        self.command = command
        self.return_code = return_code
        self.out = self._convert_to_str(out)
        self.err = self._convert_to_str(err)
        self.path = path
        self.scan_id = scan_id

    def __str__(self):
        return (
            "Scan failed with {}: command: {} return code: {} out: {} "
            "err: {}".format(
                self.message,
                self.command,
                self.return_code,
                self.out,
                self.err,
            )
        )

    @staticmethod
    def _convert_to_str(obj):
        if type(obj) is str:
            return obj
        elif type(obj) is bytes:
            return os.fsdecode(obj)
        elif type(obj) is list:
            return "".join(
                [
                    elem.decode() if type(elem) is bytes else elem
                    for elem in obj
                ]
            )
        elif obj is None:
            return ""
        else:
            raise TypeError("Unsupported type to convert to string")


class ScanAlreadyCompleteError(Exception):
    pass


class ScanInfoError(Exception):
    pass
