# Copyright 2022 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.

from dataclasses import dataclass, field
from typing import Dict, List, Optional
from serialization import serialize_fields_as

__all__ = ["PackageManifest", "PackageMetaData", "BlobEntry", "SubpackageEntry"]

from .common import FilePath


@dataclass(init=False)
@serialize_fields_as(version=str)
class PackageMetaData:
    """The metadata that describes a package.

    This is the package manifest's metadata section, which includes both
    intrinsic data like abi_revision, and extrinsic data like the name that it's
    published under and repo that it's for publishing to, etc.
    """

    name: str
    version: int = 0

    def __init__(self, name: str, version: Optional[int] = None) -> None:
        self.name = name
        if version is not None:
            self.version = version
        else:
            self.version = 0


@dataclass
class BlobEntry:
    """A blob that's in the package.

    path - The path that the blob has within the package's namespace.
    merkle - The merkle of the blob
    size - The (uncompressed) size of the blob, in bytes.
    source_path - The path to where the blob was found when the package was
                  being created.
    """

    path: FilePath
    merkle: str
    size: Optional[int] = None
    source_path: Optional[FilePath] = None

    def compare_with(
        self, other: "BlobEntry", allow_source_path_differences=False
    ) -> List[str]:
        """Compare this BlobEntry with the other, reporting any differences.

        If 'allow_source_path_differences' is True, then the source_paths of
        blobs are not compared, just the path, size, and merkle.
        """
        errors = []
        if self.size != other.size:
            errors.append(
                f"blob has a different size ({self.size} vs {other.size}) for: {self.path}"
            )
        elif self.merkle != other.merkle:
            errors.append(
                f"blob has a different merkle ({self.merkle} vs {other.merkle}) for: {self.path}"
            )
        elif not allow_source_path_differences:
            if self.source_path != other.source_path:
                errors.append(
                    f"blob has a different source ({self.source_path} vs {other.source_path}) for: {self.path}"
                )
        return errors


@dataclass
class SubpackageEntry:
    """A subpackage dependency that is directly referenced by the package.

    name - The parent-package-scoped subpackage name
    merkle - The subpackage's package hash
    manifest_path - The filesystem path to the subpackage PackageManifest
    """

    name: str
    merkle: str
    manifest_path: FilePath


@dataclass
class PackageManifest:
    """The output manifest for a Fuchsia package."""

    package: PackageMetaData
    blobs: List[BlobEntry]
    version: str = "1"
    # TODO(https://fxbug.dev/42066050): Change this to `paths_relative`, because it
    # applies to both blob source and subpackage manifest.
    blob_sources_relative: Optional[str] = None
    subpackages: List[SubpackageEntry] = field(default_factory=list)
    repository: Optional[str] = None

    def set_paths_relative(self, relative_to_file: bool):
        self.blob_sources_relative = (
            "file" if relative_to_file else "working_dir"
        )

    def blobs_by_path(self) -> Dict[FilePath, BlobEntry]:
        return {blob.path: blob for blob in self.blobs}

    def compare_with(
        self, other: "PackageManifest", allow_source_path_differences=False
    ) -> List[str]:
        """Compare this package manifest with the other, reporting any
        differences.

        If 'allow_source_path_differences' is True, then the source_paths of
        blobs are not compared, just the path, size, and merkle.
        """
        errors = []
        if self.package.name != other.package.name:
            errors.append(
                f"package publishing names differ: {self.package.name} vs. {other.package.name}"
            )

        if self.repository != other.repository:
            errors.append(
                f"package publishing repositories differ: {self.repository} vs. {other.repository}"
            )

        self_blobs_by_path = self.blobs_by_path()
        other_blobs_by_path = other.blobs_by_path()

        missing_paths = set(self_blobs_by_path.keys()).difference(
            other_blobs_by_path.keys()
        )
        extra_paths = set(other_blobs_by_path.keys()).difference(
            self_blobs_by_path.keys()
        )
        common_paths = set(self_blobs_by_path.keys()).intersection(
            other_blobs_by_path.keys()
        )

        for missing_path in missing_paths:
            errors.append(f"missing a blob for path: {missing_path}")

        for extra_path in extra_paths:
            errors.append(f"extra blob found at path: {extra_path}")

        for common_path in sorted([str(path) for path in common_paths]):
            self_blob = self_blobs_by_path[common_path]
            other_blob = other_blobs_by_path[common_path]

            errors.extend(
                self_blob.compare_with(
                    other_blob, allow_source_path_differences
                )
            )

        return errors
