// 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.

#pragma once

#include "firmware_updater_interface.hpp"
#include "host_command.hpp"

#include <boost/endian/arithmetic.hpp>

#include <array>

namespace google
{
namespace hoth
{
namespace internal
{
using namespace boost::endian;

/** @brief Equivalent of `hoth_update_region_response` in
 *  google3/host_commands.h
 */
struct HothUpdateRegionResponse
{
    little_uint32_t offset;
    little_uint32_t len;
    uint8_t flags;
};

/** @brief Equivalent of `ec_response_sps_passthrough_status` in
 *  google3/host_commands.h
 */
struct SpsPassthroughStatusResponse
{
    uint8_t enabled;
    std::array<uint8_t, 3> padding;
};

/** @brief Equivalent of `ec_spi_operation_request` in
 *  google3/host_commands.h
 */
struct EcSpiOperationHeader
{
    little_uint16_t mosiLen;
    little_uint16_t misoLen;
};

enum class ResetMode
{
    needed,
    never,
    ignore,
    needed_active,
};

/** @class FirmwareSpiUpdater class
 *  @brief Hoth firmware updater using Hoth SPI command
 */
class FirmwareSpiUpdater : public FirmwareUpdater
{
  public:
    using Base = FirmwareUpdater;

    /** @brief A RAII object to prepare and cleanup the spiWrite op(s).
     */
    class SpiWritePreparer
    {
      public:
        SpiWritePreparer(FirmwareSpiUpdater* updater, ResetMode mode);
        SpiWritePreparer(SpiWritePreparer&& preparer);
        ~SpiWritePreparer();

        SpiWritePreparer(const SpiWritePreparer&) = delete;
        SpiWritePreparer& operator=(const SpiWritePreparer&) = delete;
        SpiWritePreparer& operator=(SpiWritePreparer&&) = delete;

      private:
        FirmwareSpiUpdater* fwUpdater{nullptr};
        bool setSpsPassThoughDisabled{false};
        bool didResetTarget{false};
        ResetMode resetMode{ResetMode::needed};
    };

    /** @brief Constructor
     *
     *  @param[in] hostCmd       - Reference to the host command interface
     *  @param[in] addressSize   - SPI operation address size
     *  @param[in] targetReset   - Whether to reset target
     *  @param[in] ignoreAddressMode - Ignore address mode change failure
     */
    FirmwareSpiUpdater(HostCommand* hostCmd, uint8_t addressSize = 4,
                       ResetMode targetReset = ResetMode::never,
                       bool ignoreAddressMode = false);

    [[nodiscard]] SpiWritePreparer prepareSpiWrite();

    /** @brief Updates firmware.
     *
     *  @param[in] firmwareData - Hoth firmware image.
     */
    void update(std::vector<uint8_t> firmwareData) override;

    /** @brief SPI write to arbitrary address
     *
     *  @param[in] address - SPI offset to start writing from
     *  @param[in] data - Data to write to the SPI EEPROM
     */
    void spiWrite(uint32_t address, std::vector<uint8_t> data) override;

  private:
    /** @brief Check if update firmware with Hoth is supported
     *  Check firmware update mode supported using Hoth
     *  EC_PRV_CMD_HOTH_GET_REGION_FROM_IMG_DESC command.
     *
     *  @param[in] firmwareSize - Hoth firmware image length.
     *
     *  @return absolute address from which new firmware data can be written
     */
    uint32_t supportUpdateWithHothSpi(uint32_t firmwareSize);

    /** @brief Set/release target from reset
     *  Calls EC_PRV_CMD_HOTH_RESET_TARGET command to reset target
     *
     *  We only need to call this funciton when the build option is enabled.
     *
     *  @param[in] option - one of ec_target_reset_option enums
     */
    void resetTarget(uint8_t option);

    /** @brief Static helper function for RAII target release
     */
    static void releaseTarget(FirmwareSpiUpdater*&& updater) noexcept;

    /** @brief Check whether SPS passthrough is enabled
     *
     * If SPS passthrough is disabled, then we can send SPI commands without
     * having to reset the target.
     *
     * @return true if passthrough is enabled, false if it's disabled
     */
    bool getSpsPassthrough();

    /** @brief Set SPS passthrough mode
     *
     * If SPS passthrough is disabled, then we can send SPI commands without
     * having to reset the target.
     *
     * @param[in] enable - The desired SPS passthough mode.
     * @return indicates if the passthrough mode is successfully set.
     */
    bool setSpsPassthrough(bool enable);

    /** @brief SPI requires erase enough space before write
     *
     *  @param[in] firmwareSize - Hoth firmware image length.
     *  @param[in] address - address to erase
     */
    void erase(size_t firmwareSize, uint32_t address);

    /** @brief Writes firmwara data
     *
     *  @param[in] firmwareData - Hoth firmware image.
     *  @param[in] address - address to write
     */
    void writeData(const std::vector<uint8_t>& firmwareData, uint32_t address);

    /** @brief Reads back data and verifies it matches input firmware
     *
     *  @param[in] firmwareData - Hoth firmware image.
     *  @param[in] address - address to read
     */
    void verifyData(const std::vector<uint8_t>& firmwareData, uint32_t address);

    /** @brief Appends 3 or 4 byte address to `array` depending on `addressSize`
     *
     *  @param[in] array   - byte array
     *  @param[in] address - address
     */
    void appendAddress(std::vector<uint8_t>& array, uint32_t address);

    /** @brief The actual firmware update operation.
     *
     *  @param[in] firmwareData - data
     *  @param[in] address - address
     */
    void doUpdate(const std::vector<uint8_t>& data, uint32_t address);

    /** @brief Connection to Hoth for sending and receiving host commands */
    HostCommand* hostCmd;

    /** @brief SPI operation address size, it can be 3 or 4 bytes */
    uint8_t addressSize;

    /** @brief Whether set target to reset before SPI */
    ResetMode targetReset;

    /** @brief Whether to ignore address mode change failure */
    bool ignoreAddressMode;
};
} // namespace internal
} // namespace hoth
} // namespace google
