# Copyright (C) 2015-2020  The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information

"""Convert objects to dictionaries suitable for swh.storage"""

import logging

from typing import Dict, Iterable, List, Optional, Tuple

from swh.model.hashutil import hash_to_hex
from swh.model.model import BaseContent, Content, SkippedContent


logger = logging.getLogger(__name__)


def prepare_contents(
        contents: Iterable[Dict], max_content_size: Optional[int] = None,
        origin_url: Optional[str] = None) -> Tuple[
            List[Dict], List[Dict]]:
    """Prepare contents for storage from a list of contents

    Returns
        tuple of content iterable, skipped content iterable

    """
    present_contents: List[Dict] = []
    skipped_contents: List[Dict] = []
    for _content in contents:
        content = content_for_storage(
            _content, max_content_size=max_content_size, origin_url=origin_url)
        if isinstance(content, SkippedContent):
            skipped_contents.append(content.to_dict())
        else:
            present_contents.append(content.to_dict())
    return present_contents, skipped_contents


def content_for_storage(
        content: Dict, max_content_size: Optional[int] = None,
        origin_url: Optional[str] = None) -> BaseContent:
    """Prepare content to be ready for storage

    Note:
    - 'data' is returned only if max_content_size is not reached.

    Returns:
        content with added data (or reason for being missing)

    """
    ret = content.copy()
    ret.pop('perms', None)

    if max_content_size and ret['length'] > max_content_size:
        logger.info('Skipping content %s, too large (%s > %s)' %
                    (hash_to_hex(content['sha1_git']),
                     ret['length'],
                     max_content_size))
        ret.pop('data', None)
        ret.update({'status': 'absent',
                    'reason': 'Content too large',
                    'origin': origin_url})
        return SkippedContent.from_dict(ret)

    if 'data' not in ret:
        with open(ret['path'], 'rb') as f:
            ret['data'] = f.read()

    # Extra keys added by swh.model.from_disk, that are not accepted
    # by swh-storage
    ret.pop('path', None)

    ret['status'] = 'visible'

    return Content.from_dict(ret)
