# -*- coding: utf-8 -*-

#   COPYRIGHT NOTICE STARTS HERE

#   Copyright 2019 © Samsung Electronics Co., Ltd.
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

#   COPYRIGHT NOTICE ENDS HERE

import logging
from abc import ABC, abstractmethod

import prettytable

log = logging.getLogger(__name__)


class AbstractDownloader(ABC):

    def __init__(self, list_type, *list_args):
        self._list_type = list_type
        self._data_list = {item: list_arg[1] for list_arg in list_args
                           for item in self.load_list(list_arg[0])}
        self._missing = self.missing()

    @property
    def list_type(self):
        """
        Type of resource in list
        """
        return self._list_type

    @staticmethod
    def load_list(path):
        """
        Load list from file.
        :param path: path to file
        :return: set of items in list
        """
        with open(path, 'r') as f:
            return {item for item in (line.strip() for line in f)
                    if item and not item.startswith('#')}

    @staticmethod
    def _check_table(header, alignment_dict, data):
        """
        General method to generate table
        :param header: header of the table
        :param alignment_dict: dictionary with alignment for columns
        :param data: iterable of rows of table
        :return: table formatted data
        """
        table = prettytable.PrettyTable(header)

        for k, v in alignment_dict.items():
            table.align[k] = v

        for row in sorted(data):
            table.add_row(row)

        return table

    @abstractmethod
    def download(self):
        """
        Download resources from lists
        """
        pass

    @abstractmethod
    def _is_missing(self, item):
        """
        Check if item is not downloaded
        """
        pass

    def missing(self):
        """
        Check for missing data (not downloaded)
        :return: dictionary of missing items
        """
        self._missing = {item: dst for item, dst in self._data_list.items() if
                         self._is_missing(item)}
        return self._missing

    def _log_existing(self):
        """
        Log items that are already downloaded.
        """
        for item in self._merged_lists():
            if item not in self._missing:
                if type(self).__name__ == 'DockerDownloader':
                    log.info('Docker image present: {}'.format(item))
                else:
                    log.info('File or directory present: {}'.format(item))

    def _merged_lists(self):
        """
        Get all item names in one set
        :return: set with all items
        """
        return set(self._data_list.keys())

    def _initial_log(self):
        """
        Log initial info for download.
        :return: True if download is necessary False if everything is already downloaded
        """
        self._log_existing()
        items_left = len(self._missing)
        class_name = type(self).__name__
        if items_left == 0:
            log.info('{}: Everything seems to be present no download necessary.'.format(class_name))
            return False
        log.info('{}: Initializing download {} {} are not present.'.format(class_name, items_left,
                                                                           self._list_type))
        return True
