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

# Implement some special endpoints used to provide input tests data
# when executing end to end tests with cypress

import os

from typing import Dict

from rest_framework.decorators import api_view
from rest_framework.response import Response

from swh.model import from_disk
from swh.model.hashutil import hash_to_hex
from swh.model.model import Content
from swh.web.common.highlightjs import get_hljs_language_from_filename
from swh.web.config import get_config
from swh.web.tests.data import get_tests_data

_content_code_data_exts = {}  # type: Dict[str, Dict[str, str]]
_content_code_data_filenames = {}  # type: Dict[str, Dict[str, str]]
_content_other_data_exts = {}  # type: Dict[str, Dict[str, str]]


def _init_content_tests_data(data_path, data_dict, ext_key):
    """
    Helper function to read the content of a directory, store it
    into a test archive and add some files metadata (sha1 and/or
    expected programming language) in a dict.

    Args:
        data_path (str): path to a directory relative to the tests
            folder of swh-web
        data_dict (dict): the dict that will store files metadata
        ext_key (bool): whether to use file extensions or filenames
            as dict keys
    """
    test_contents_dir = os.path.join(
        os.path.dirname(__file__), data_path).encode('utf-8')
    directory = from_disk.Directory.from_disk(path=test_contents_dir)

    contents = []
    for name, obj in directory.items():
        if isinstance(obj, from_disk.Content):
            c = obj.to_model().with_data().to_dict()
            c['status'] = 'visible'
            sha1 = hash_to_hex(c['sha1'])
            if ext_key:
                key = name.decode('utf-8').split('.')[-1]
                filename = 'test.' + key
            else:
                filename = name.decode('utf-8').split('/')[-1]
                key = filename
            language = get_hljs_language_from_filename(filename)
            data_dict[key] = {'sha1': sha1,
                              'language': language}
            contents.append(Content.from_dict(c))
    storage = get_tests_data()['storage']
    storage.content_add(contents)


def _init_content_code_data_exts():
    """
    Fill a global dictionary which maps source file extension to
    a code content example.
    """
    global _content_code_data_exts
    _init_content_tests_data('resources/contents/code/extensions',
                             _content_code_data_exts, True)


def _init_content_other_data_exts():
    """
    Fill a global dictionary which maps a file extension to
    a content example.
    """
    global _content_other_data_exts
    _init_content_tests_data('resources/contents/other/extensions',
                             _content_other_data_exts, True)


def _init_content_code_data_filenames():
    """
    Fill a global dictionary which maps a filename to
    a content example.
    """
    global _content_code_data_filenames
    _init_content_tests_data('resources/contents/code/filenames',
                             _content_code_data_filenames, False)


if get_config()['e2e_tests_mode']:
    _init_content_code_data_exts()
    _init_content_other_data_exts()
    _init_content_code_data_filenames()


@api_view(['GET'])
def get_content_code_data_all_exts(request):
    """
    Endpoint implementation returning a list of all source file
    extensions to test for highlighting using cypress.
    """
    return Response(sorted(_content_code_data_exts.keys()),
                    status=200, content_type='application/json')


@api_view(['GET'])
def get_content_code_data_by_ext(request, ext):
    """
    Endpoint implementation returning metadata of a code content example
    based on the source file extension.
    """
    data = None
    status = 404
    if ext in _content_code_data_exts:
        data = _content_code_data_exts[ext]
        status = 200
    return Response(data, status=status, content_type='application/json')


@api_view(['GET'])
def get_content_other_data_by_ext(request, ext):
    """
    Endpoint implementation returning metadata of a content example
    based on the file extension.
    """
    _init_content_other_data_exts()
    data = None
    status = 404
    if ext in _content_other_data_exts:
        data = _content_other_data_exts[ext]
        status = 200
    return Response(data, status=status, content_type='application/json')


@api_view(['GET'])
def get_content_code_data_all_filenames(request):
    """
    Endpoint implementation returning a list of all source filenames
    to test for highlighting using cypress.
    """
    return Response(sorted(_content_code_data_filenames.keys()),
                    status=200, content_type='application/json')


@api_view(['GET'])
def get_content_code_data_by_filename(request, filename):
    """
    Endpoint implementation returning metadata of a code content example
    based on the source filename.
    """
    data = None
    status = 404
    if filename in _content_code_data_filenames:
        data = _content_code_data_filenames[filename]
        status = 200
    return Response(data, status=status, content_type='application/json')
