# Copyright 2021 The Pigweed Authors
#
# 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
#
#     https://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.
"""Library to assist processing Snapshot Metadata protos into text"""

from typing import Optional, List, Mapping
import pw_log_tokenized
import pw_tokenizer
from pw_tokenizer import proto as proto_detokenizer
from pw_snapshot_metadata_proto import snapshot_metadata_pb2

_PRETTY_FORMAT_DEFAULT_WIDTH = 80


def _process_tags(tags: Mapping[str, str]) -> Optional[str]:
    """Outputs snapshot tags as a multi-line string."""
    if not tags:
        return None

    output: List[str] = ['Tags:']
    for key, value in tags.items():
        output.append(f'  {key}: {value}')

    return '\n'.join(output)


def process_snapshot(serialized_snapshot: bytes,
                     tokenizer_db: Optional[pw_tokenizer.Detokenizer]) -> str:
    """Processes snapshot metadata and tags, producing a multi-line string."""
    snapshot = snapshot_metadata_pb2.SnapshotBasicInfo()
    snapshot.ParseFromString(serialized_snapshot)

    output: List[str] = []

    if snapshot.HasField('metadata'):
        output.extend((
            str(MetadataProcessor(snapshot.metadata, tokenizer_db)),
            '',
        ))

    if snapshot.tags:
        tags = _process_tags(snapshot.tags)
        if tags:
            output.append(tags)
        # Trailing blank line for spacing.
        output.append('')

    return '\n'.join(output)


class MetadataProcessor:
    """This class simplifies dumping contents of a snapshot Metadata message."""
    def __init__(self, metadata: snapshot_metadata_pb2.Metadata,
                 tokenizer_db: Optional[pw_tokenizer.Detokenizer]):
        self._metadata = metadata
        self._tokenizer_db = (tokenizer_db if tokenizer_db is not None else
                              pw_tokenizer.Detokenizer(None))
        self._reason_token = self._tokenizer_db.detokenize(
            metadata.reason).token
        self._format_width = _PRETTY_FORMAT_DEFAULT_WIDTH
        proto_detokenizer.detokenize_fields(self._tokenizer_db, self._metadata)

    def is_fatal(self) -> bool:
        return self._metadata.fatal

    def reason(self) -> str:
        if not self._metadata.reason:
            return 'UNKNOWN (field missing)'

        log = pw_log_tokenized.FormatStringWithMetadata(
            self._metadata.reason.decode())

        return f'{log.file}: {log.message}' if log.file else log.message

    def reason_token(self) -> Optional[int]:
        """If the snapshot `reason` is tokenized, the value of the token."""
        return self._reason_token

    def project_name(self) -> str:
        return self._metadata.project_name.decode()

    def device_name(self) -> str:
        return self._metadata.device_name.decode()

    def device_fw_version(self) -> str:
        return self._metadata.software_version

    def snapshot_uuid(self) -> str:
        return self._metadata.snapshot_uuid.hex()

    def fw_build_uuid(self) -> str:
        return self._metadata.software_build_uuid.hex()

    def set_pretty_format_width(self, width: int):
        """Sets the centered width of the FATAL text for a formatted output."""
        self._format_width = width

    def __str__(self) -> str:
        """outputs a pw.snapshot.Metadata proto as a multi-line string."""
        output: List[str] = []
        if self._metadata.fatal:
            output.extend((
                '▪▄▄▄ ▄▄▄· ▄▄▄▄▄ ▄▄▄· ▄ ·'.center(self._format_width).rstrip(),
                '█▄▄▄▐█ ▀█ • █▌ ▐█ ▀█ █  '.center(self._format_width).rstrip(),
                '█ ▪ ▄█▀▀█   █. ▄█▀▀█ █  '.center(self._format_width).rstrip(),
                '▐▌ .▐█ ▪▐▌ ▪▐▌·▐█ ▪▐▌▐▌ '.center(self._format_width).rstrip(),
                '▀    ▀  ▀ ·  ▀  ▀  ▀ .▀▀'.center(self._format_width).rstrip(),
                '',
                'Device crash cause:',
            ))
        else:
            output.append('Snapshot capture reason:')

        output.extend((
            '    ' + self.reason(),
            '',
        ))
        if self.reason_token():
            output.append(f'Reason token:      0x{self.reason_token():x}')

        if self._metadata.project_name:
            output.append(f'Project name:      {self.project_name()}')

        if self._metadata.device_name:
            output.append(f'Device:            {self.device_name()}')

        if self._metadata.software_version:
            output.append(f'Device FW version: {self.device_fw_version()}')

        if self._metadata.software_build_uuid:
            output.append(f'FW build UUID:     {self.fw_build_uuid()}')

        if self._metadata.snapshot_uuid:
            output.append(f'Snapshot UUID:     {self.snapshot_uuid()}')

        return '\n'.join(output)
