#
#   Copyright © 2021,2022 IsardVDI S.L.
#   Copyright © 2022 Evilham <contact@evilham.com>
#
#   This file is part of DD
#
#   DD 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.
#
#   DD 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 DD. If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: AGPL-3.0-or-later
import logging as log
import os
from pprint import pprint

from minio import Minio
from minio.commonconfig import REPLACE, CopySource
from minio.deleteobjects import DeleteObject
from requests import get, post

from typing import Any, Callable, Dict, Iterable, List


class Avatars:
    avatars_path : str
    def __init__(self, avatars_path : str):
        self.avatars_path = avatars_path
        self.mclient = Minio(
            os.environ["AVATARS_SERVER_HOST"],
            access_key=os.environ["AVATARS_ACCESS_KEY"],
            secret_key=os.environ["AVATARS_SECRET_KEY"],
            secure=bool(os.environ.get("AVATARS_SECURE", "")),
        )
        self.bucket = "master-avatars"
        self._minio_set_realm()
        # self.update_missing_avatars()

    def add_user_default_avatar(self, userid : str, role : str="unknown") -> None:
        path = os.path.join(self.avatars_path, role) + ".jpg"
        self.mclient.fput_object(
            self.bucket,
            userid,
            path,
            content_type="image/jpeg ",
        )
        log.warning(
            " AVATARS: Updated avatar for user " + userid + " with role " + role
        )

    def delete_user_avatar(self, userid : str) -> None:
        self.minio_delete_object(userid)

    def update_missing_avatars(self, users : Iterable[Dict[str, Any]]) -> None:
        sys_roles = ["admin", "manager", "teacher", "student"]
        for u in self.get_users_without_image(users):
            try:
                img = [r + ".jpg" for r in sys_roles if r in u["roles"]][0]
            except:
                img = "unknown.jpg"

            path = os.path.join(self.avatars_path, img)
            self.mclient.fput_object(
                self.bucket,
                u["id"],
                path,
                content_type="image/jpeg ",
            )
            log.warning(
                " AVATARS: Updated avatar for user "
                + u["username"]
                + " with role "
                + img.split(".")[0]
            )

    def _minio_set_realm(self) -> None:
        if not self.mclient.bucket_exists(self.bucket):
            self.mclient.make_bucket(self.bucket)

    def minio_get_objects(self) -> List[Any]:
        return [o.object_name for o in self.mclient.list_objects(self.bucket)]

    def minio_delete_all_objects(self) -> None:
        f : Callable[[Any], Any] = lambda x: DeleteObject(x.object_name)
        delete_object_list = map(f, self.mclient.list_objects(self.bucket))
        errors = self.mclient.remove_objects(self.bucket, delete_object_list)
        for error in errors:
            log.error(" AVATARS: Error occured when deleting avatar object: " + error)

    def minio_delete_object(self, oid : str) -> None:
        errors = self.mclient.remove_objects(self.bucket, [DeleteObject(oid)])
        for error in errors:
            log.error(" AVATARS: Error occured when deleting avatar object: " + error)

    def get_users_without_image(self, users : Iterable[Dict[str, Any]]) -> Iterable[Dict[str, Any]]:
        return [u for u in users if u["id"] and u["id"] not in self.minio_get_objects()]
