// Copyright 2024 Google LLC
//
// 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.

#include "payload_update_cli.hpp"

#include "google3/host_commands.h"

#include "dbus_interface.hpp"
#include "parser.hpp"
#include "payload_update_common.hpp"

#include <iostream>

namespace google::hoth::tools
{
namespace payload_update
{
bool PayloadUpdateCLI::doUpdate()
{
    bool didReset = false;

    if (!args.hothId.empty())
    {
        if (args.reset != ResetMode::kNever)
        {
            std::optional<bool> res;
            try
            {
                res = dbus->getSpsPassthrough(args.hothId);
            }
            catch (const std::exception& e)
            {
                std::cerr << "Failed to get SPS passthrough status: " << e.what()
                          << '\n';
            }
            if (!res && args.reset == ResetMode::kIgnore)
            {
                std::cerr << "Ignoring failed SPS passthrough status command"
                          << '\n';
            }
            else if (res.value_or(true))
            {
                std::cerr << "Target did not report SPS passthrough disabled. "
                            "Attempting reset"
                          << '\n';
                if (!dbus->setTargetResetOption(args.hothId,
                                                EC_TARGET_RESET_OPTION_SET))
                {
                    std::cerr << "Failed to put target into reset" << '\n';
                    return false;
                }
                didReset = true;
            }
        }
        if (args.spsPassthrough && !dbus->setSpsPassthrough(args.hothId, false))
        {
            std::cerr << "Failed to disable SPS passthrough" << '\n';
            return false;
        }
    }
    if (args.payloadUpdateMode == UpdateMode::kUpdateStaticWPRegions)
    {
        if (!dbus->sendStaticWPPayloadAndVerify(args.hothId,
                                                args.payloadFilename))
        {
            std::cerr << "Failed to send payload (STATIC & WP) and verify"
                      << '\n';
            return false;
        }
    }
    else
    {
        if (!dbus->eraseStagingArea(args.hothId))
        {
            std::cerr << "Failed to erase staging area" << '\n';
            return false;
        }
        if (!dbus->sendPayloadAndVerify(args.hothId, args.payloadFilename))
        {
            std::cerr << "Failed to send payload and verify" << '\n';
            return false;
        }
    }
    if (!dbus->activatePayload(args.hothId))
    {
        std::cerr << "Faild to activate payload" << '\n';
        return false;
    }

    if (args.hothId.empty() && !dbus->expectConfirmPayload())
    {
        std::cerr << "Failed to enable payload confirm" << '\n';
        return false;
    }

    if (!args.hothId.empty())
    {
        if (args.spsPassthrough && !dbus->setSpsPassthrough(args.hothId, true))
        {
            std::cerr << "Failed to enable SPS passthrough" << '\n';
            return false;
        }
        if (didReset)
        {
            if (!dbus->setTargetResetOption(args.hothId,
                                            EC_TARGET_RESET_OPTION_RELEASE))
            {
                std::cerr << "Failed to release target from reset" << '\n';
                return false;
            }
        }
    }
    return true;
}

bool PayloadUpdateCLI::getOptions()
{
    return parser->parse(args);
}

bool PayloadUpdateCLI::execute()
{
    switch (args.command)
    {
        using enum payload_update::SubCommandType;
        case kVersion:
        {
            auto version =
                dbus->getPayloadVersion(args.hothId, args.versionType);
            if (version != std::nullopt)
            {
              std::cout << *version << '\n';
              return true;
            }
            return false;
        }
        case kUpdate:
            return doUpdate();
        default:
            break;
    }
    return true;
}
} // namespace payload_update
} // namespace google::hoth::tools
