# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for downloading and packaging fonts."""

from collections import namedtuple

DEPS = [
    "fuchsia/git",
    "fuchsia/upload",
    "recipe_engine/cipd",
    "recipe_engine/file",
    "recipe_engine/path",
    "recipe_engine/step",
]

Repository = namedtuple("Repository", ["url", "ref", "fonts"])
Font = namedtuple("Font", ["name", "path", "files", "license"])

REPOSITORIES = [
    Repository(
        url="https://github.com/google/fonts",
        ref="94dff3eaa9301b6640cccc63c56d6ff33d82882c",
        fonts=[
            Font(
                name="roboto",
                path=("apache", "roboto"),
                files=[
                    "Roboto-BlackItalic.ttf",
                    "Roboto-Black.ttf",
                    "Roboto-BoldItalic.ttf",
                    "Roboto-Bold.ttf",
                    "Roboto-Italic.ttf",
                    "Roboto-LightItalic.ttf",
                    "Roboto-Light.ttf",
                    "Roboto-MediumItalic.ttf",
                    "Roboto-Medium.ttf",
                    "Roboto-Regular.ttf",
                    "Roboto-ThinItalic.ttf",
                    "Roboto-Thin.ttf",
                ],
                license=("apache", "roboto", "LICENSE.txt"),
            ),
            Font(
                name="robotocondensed",
                path=("apache", "robotocondensed"),
                files=[
                    "RobotoCondensed-BoldItalic.ttf",
                    "RobotoCondensed-Bold.ttf",
                    "RobotoCondensed-Italic.ttf",
                    "RobotoCondensed-LightItalic.ttf",
                    "RobotoCondensed-Light.ttf",
                    "RobotoCondensed-Regular.ttf",
                ],
                license=("apache", "robotocondensed", "LICENSE.txt"),
            ),
            Font(
                name="robotomono",
                path=("apache", "robotomono"),
                files=[
                    "RobotoMono-BoldItalic.ttf",
                    "RobotoMono-Bold.ttf",
                    "RobotoMono-Italic.ttf",
                    "RobotoMono-LightItalic.ttf",
                    "RobotoMono-Light.ttf",
                    "RobotoMono-MediumItalic.ttf",
                    "RobotoMono-Medium.ttf",
                    "RobotoMono-Regular.ttf",
                    "RobotoMono-ThinItalic.ttf",
                    "RobotoMono-Thin.ttf",
                ],
                license=("apache", "robotomono", "LICENSE.txt"),
            ),
            Font(
                name="robotoslab",
                path=("apache", "robotoslab"),
                files=[
                    "RobotoSlab-Bold.ttf",
                    "RobotoSlab-Light.ttf",
                    "RobotoSlab-Regular.ttf",
                    "RobotoSlab-Thin.ttf",
                ],
                license=("apache", "robotoslab", "LICENSE.txt"),
            ),
        ],
    ),
    Repository(
        url="https://github.com/google/material-design-icons",
        ref="224895a86501195e7a7ff3dde18e39f00b8e3d5a",
        fonts=[
            Font(
                name="material",
                path=("iconfont",),
                files=["MaterialIcons-Regular.ttf"],
                license=("LICENSE",),
            ),
        ],
    ),
    Repository(
        url="https://github.com/googlei18n/noto-cjk",
        ref="9326451d9b4f32ec7f8640581c5053cc192039f2",
        fonts=[
            Font(
                name="noto-cjk",
                path=(),
                files=[
                    "NotoSansCJK-Black.ttc",
                    "NotoSansCJK-Bold.ttc",
                    "NotoSansCJK-DemiLight.ttc",
                    "NotoSansCJK-Light.ttc",
                    "NotoSansCJK-Medium.ttc",
                    "NotoSansCJK-Regular.ttc",
                    "NotoSansCJK-Thin.ttc",
                    "NotoSerifCJK-Black.ttc",
                    "NotoSerifCJK-Bold.ttc",
                    "NotoSerifCJK-ExtraLight.ttc",
                    "NotoSerifCJK-Light.ttc",
                    "NotoSerifCJK-Medium.ttc",
                    "NotoSerifCJK-Regular.ttc",
                    "NotoSerifCJK-SemiBold.ttc",
                ],
                license=("LICENSE",),
            ),
        ],
    ),
]


def RunSteps(api):
    cipd_pkg_dir = api.path["start_dir"].join("fonts")
    api.file.ensure_directory("makedirs", cipd_pkg_dir)

    git_repositories = []

    for repository in REPOSITORIES:
        repository_name = repository.url.rsplit("/", 1)[-1]
        with api.step.nest(repository_name):
            src_dir = api.path["start_dir"].join("src", repository_name)
            git_sha = api.git.checkout(repository.url, src_dir, ref=repository.ref)
            git_repositories.append((repository.url, git_sha))

            for font in repository.fonts:
                with api.step.nest(font.name):
                    pkg_dir = cipd_pkg_dir.join(font.name)
                    api.file.ensure_directory("make %s dir" % font.name, pkg_dir)

                    for filename in font.files:
                        path = list(font.path) + [filename]
                        api.file.copy(filename, src_dir.join(*path), pkg_dir)
                    api.file.copy(
                        font.license[-1], src_dir.join(*font.license), pkg_dir
                    )

    git_repositories.sort()
    git_repository = ",".join(r for r, _ in git_repositories)
    git_revision = ",".join(r for _, r in git_repositories)
    api.upload.cipd_package(
        "fuchsia/third_party/fonts",
        cipd_pkg_dir,
        [api.upload.DirectoryPath(cipd_pkg_dir)],
        {"git_revision": git_revision},
        repository=git_repository,
    )


def GenTests(api):
    cipd_pkg_name = "fuchsia/third_party/fonts"
    yield (
        api.test("existing")
        + api.step_data(
            "cipd.cipd search "
            + cipd_pkg_name
            + " git_revision:deadbeef,deadbeef,deadbeef",
            api.cipd.example_search(cipd_pkg_name, []),
        )
    )
    yield (api.test("new"))
