#!/usr/bin/env python
#
# Copyright 2016 - The Android Open Source Project
#
# 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
#
#     http://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.

"""Command report.

Report class holds the results of a command execution.
Each driver API call will generate a report instance.

If running the CLI of the driver, a report will
be printed as logs. And it will also be dumped to a json file
if requested via command line option.

The json format of a report dump looks like:

  - A failed "delete" command:
  {
    "command": "delete",
    "data": {},
    "errors": [
      "Can't find instances: ['104.197.110.255']"
    ],
    "status": "FAIL"
  }

  - A successful "create" command:
  {
    "command": "create",
    "data": {
       "devices": [
          {
            "instance_name": "instance_1",
            "ip": "104.197.62.36"
          },
          {
            "instance_name": "instance_2",
            "ip": "104.197.62.37"
          }
       ]
    },
    "errors": [],
    "status": "SUCCESS"
  }
"""

import json
import logging
import os

logger = logging.getLogger(__name__)


class Status(object):
    """Status of acloud command."""

    SUCCESS = "SUCCESS"
    FAIL = "FAIL"
    BOOT_FAIL = "BOOT_FAIL"
    UNKNOWN = "UNKNOWN"

    SEVERITY_ORDER = {UNKNOWN: 0, SUCCESS: 1, FAIL: 2, BOOT_FAIL: 3}

    @classmethod
    def IsMoreSevere(cls, candidate, reference):
        """Compare the severity of two statuses.

        Args:
            candidate: One of the statuses.
            reference: One of the statuses.

        Returns:
            True if candidate is more severe than reference,
            False otherwise.

        Raises:
            ValueError: if candidate or reference is not a known state.
        """
        if (candidate not in cls.SEVERITY_ORDER or
                reference not in cls.SEVERITY_ORDER):
            raise ValueError(
                "%s or %s is not recognized." % (candidate, reference))
        return cls.SEVERITY_ORDER[candidate] > cls.SEVERITY_ORDER[reference]


class Report(object):
    """A class that stores and generates report."""

    def __init__(self, command):
        """Initialize.

        Args:
            command: A string, name of the command.
        """
        self.command = command
        self.status = Status.UNKNOWN
        self.errors = []
        self.data = {}

    def AddData(self, key, value):
        """Add a key-val to the report.

        Args:
            key: A key of basic type.
            value: A value of any json compatible type.
        """
        self.data.setdefault(key, []).append(value)

    def AddError(self, error):
        """Add error message.

        Args:
            error: A string.
        """
        self.errors.append(error)

    def AddErrors(self, errors):
        """Add a list of error messages.

        Args:
            errors: A list of string.
        """
        self.errors.extend(errors)

    def SetStatus(self, status):
        """Set status.

        Args:
            status: One of the status in Status.
        """
        if Status.IsMoreSevere(status, self.status):
            self.status = status
        else:
            logger.debug(
                "report: Current status is %s, "
                "requested to update to a status with lower severity %s, ignored.",
                self.status, status)

    def Dump(self, report_file):
        """Dump report content to a file.

        Args:
            report_file: A path to a file where result will be dumped to.
                         If None, will only output result as logs.
        """
        result = dict(
            command=self.command,
            status=self.status,
            errors=self.errors,
            data=self.data)
        logger.info("Report: %s", json.dumps(result, indent=2))
        if not report_file:
            return
        try:
            with open(report_file, "w") as f:
                json.dump(result, f, indent=2)
            logger.info("Report file generated at %s",
                        os.path.abspath(report_file))
        except OSError as e:
            logger.error("Failed to dump report to file: %s", str(e))
