/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 "OTAImageProcessorImpl.h"
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>

#ifdef BOOT_ENABLED
#include "bootutil/bootutil.h"
#include "flash_map_backend/secondary_bd.h"
#include "platform/mbed_power_mgmt.h"
#include "rtos/ThisThread.h"
#endif

using namespace ::chip::DeviceLayer::Internal;

namespace chip {

OTAImageProcessorImpl::OTAImageProcessorImpl()
{
#ifdef BOOT_ENABLED
    // Set block device - memory for image update
    mBlockDevice = get_secondary_bd();
#endif
}

int OTAImageProcessorImpl::MemoryTest()
{
    int ret = 0;
    bd_size_t read_size;
    bd_size_t program_size;
    bd_size_t erase_size;
    bd_size_t full_size;
    size_t buffer_size;
    char * buffer = nullptr;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Initialize the block device
    ret = mBlockDevice->init();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device initialization failed [%d]", ret);
        goto exit;
    }

    // Get the block device type
    ChipLogProgress(SoftwareUpdate, "Block device type: %s", mBlockDevice->get_type());

    // Get device geometry
    read_size    = mBlockDevice->get_read_size();
    program_size = mBlockDevice->get_program_size();
    erase_size   = mBlockDevice->get_erase_size();
    full_size    = mBlockDevice->size();

    ChipLogProgress(SoftwareUpdate, "--- Block device geometry ---");
    ChipLogProgress(SoftwareUpdate, "read_size:    %lld B", read_size);
    ChipLogProgress(SoftwareUpdate, "program_size: %lld B", program_size);
    ChipLogProgress(SoftwareUpdate, "erase_size:   %lld B", erase_size);
    ChipLogProgress(SoftwareUpdate, "size:         %lld B", full_size);
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Allocate a block with enough space for our data, aligned to the
    // nearest program_size. This is the minimum size necessary to write
    // data to a block.
    buffer_size = sizeof("Hello Storage!") + program_size - 1;
    buffer_size = buffer_size - (buffer_size % program_size);
    buffer      = new char[buffer_size];

    // Read what is currently stored on the block device. We haven't written
    // yet so this may be garbage
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Currently stored data ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
        }
        ChipLogProgress(SoftwareUpdate, " ");
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Write data to first block, write occurs in two parts,
    // an erase followed by a program
    ret = mBlockDevice->erase(0, erase_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device erase failed [%d]", ret);
        goto exit;
    }

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);

    // Read the data from the first block
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Stored data after erase ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
            ChipLogProgress(SoftwareUpdate, " ");
        }
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);
    // Update buffer with our string we want to store
    strncpy(buffer, "Hello Storage!", buffer_size);

    ret = mBlockDevice->program(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device program failed [%d]", ret);
        goto exit;
    }

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);

    // Read the data from the first block, note that the program_size must be
    // a multiple of the read_size, so we don't have to check for alignment
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Stored data after write ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
        }

        ChipLogProgress(SoftwareUpdate, " %.*s", buffer_size - i, &buffer[i]);
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    ret = strcmp(buffer, "Hello Storage!");
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Data compare failed");
    }
    else
    {
        ChipLogProgress(SoftwareUpdate, "--- MEMORY TEST PASS ---");
    }

exit:
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "--- MEMORY TEST FAILED ---");
    }

    if (buffer)
    {
        delete buffer;
    }
    // Deinitialize the block device
    ret = mBlockDevice->deinit();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block deinitialization read failed [%d]", ret);
        goto exit;
    }

    return ret;
}

CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
{
    ChipLogProgress(SoftwareUpdate, "Prepare download");
    ClearDownloadParams();
    DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Finalize()
{
    ChipLogProgress(SoftwareUpdate, "Finalize");
    DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Apply()
{
    ChipLogProgress(SoftwareUpdate, "Apply");
    DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Abort()
{
    ChipLogProgress(SoftwareUpdate, "Abort");
    ClearDownloadParams();
    DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
};

CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
{
    ChipLogProgress(SoftwareUpdate, "Process block");
    CHIP_ERROR err = SetBlock(block);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }
    DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }
    else if (imageProcessor->mDownloader == nullptr)
    {
        ChipLogError(SoftwareUpdate, "mDownloader is null");
        return;
    }

    auto ret = imageProcessor->PrepareMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Prepare download memory failed");
        imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_INTERNAL);
        return;
    }

    ret = imageProcessor->ClearMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Clear download memory failed");
        imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_INTERNAL);
        return;
    }
    imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
}

void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

    imageProcessor->mParams.totalFileBytes = imageProcessor->mParams.downloadedBytes;
    imageProcessor->ReleaseBlock();
    auto ret = imageProcessor->CloseMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Close download memory failed");
    }
    ChipLogProgress(SoftwareUpdate, "OTA image downloaded size %lldB", imageProcessor->mParams.totalFileBytes);
}

void OTAImageProcessorImpl::HandleAbort(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

    auto ret = imageProcessor->ClearMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Clear download memory failed");
    }

    ret = imageProcessor->CloseMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Close download memory failed");
    }

    imageProcessor->ReleaseBlock();
}

void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }
    else if (imageProcessor->mDownloader == nullptr)
    {
        ChipLogError(SoftwareUpdate, "mDownloader is null");
        return;
    }

    auto ret = imageProcessor->ProgramMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Program download memory failed");
    }
    imageProcessor->mDownloader->FetchNextData();
}

void OTAImageProcessorImpl::HandleApply(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

#ifdef BOOT_ENABLED
    ChipLogProgress(SoftwareUpdate, "Set secondary image pending");
    auto ret = boot_set_pending_multi(/*image index*/ 0, /*permanent*/ 0);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Setting the update candidate as pending failed: %d", ret);
    }

    // Restart the device
    ChipLogProgress(SoftwareUpdate, "Device restarting....");
    rtos::ThisThread::sleep_for(3000);
    system_reset();
#endif
}

CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
{
    if (!IsSpanUsable(block))
    {
        ReleaseBlock();
        return CHIP_NO_ERROR;
    }
    if (mBlock.size() < block.size())
    {
        if (!mBlock.empty())
        {
            ReleaseBlock();
        }

        size_t buffer_size = 0;
        if (mBlockDevice)
        {
            // Aligned to the nearest program_size. This is the minimum size necessary to write data to a block.
            bd_size_t program_size = mBlockDevice->get_program_size();
            buffer_size            = block.size() + program_size - 1;
            buffer_size            = buffer_size - (buffer_size % program_size);
        }
        else
        {
            buffer_size = block.size();
        }

        uint8_t * mBlock_ptr = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(buffer_size));
        if (mBlock_ptr == nullptr)
        {
            return CHIP_ERROR_NO_MEMORY;
        }
        mBlock = MutableByteSpan(mBlock_ptr, buffer_size);
    }
    CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
{
    if (mBlock.data() != nullptr)
    {
        chip::Platform::MemoryFree(mBlock.data());
    }
    mBlock = MutableByteSpan();
    return CHIP_NO_ERROR;
}

void OTAImageProcessorImpl::ClearDownloadParams()
{
    mParams.downloadedBytes = 0;
    mParams.totalFileBytes  = 0;
}

int OTAImageProcessorImpl::PrepareMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Initialize the block device
    ret = mBlockDevice->init();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device initialization failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate, "Block device initialize");

    // Initialization read from the block device
    bd_size_t read_size = mBlockDevice->get_read_size();
    char buff[read_size];
    ret = mBlockDevice->read(&buff, 0, read_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        return ret;
    }

    return ret;
}

int OTAImageProcessorImpl::CloseMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Deinitialize the block device
    ret = mBlockDevice->deinit();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device deinitialization failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate, "Block device deinitialization");

    return ret;
}

int OTAImageProcessorImpl::ClearMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Erase memory of block device
    ret = mBlockDevice->erase(0, mBlockDevice->size());
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Erase block device failed [%d]", ret);
        return ret;
    }

    return ret;
}

int OTAImageProcessorImpl::ProgramMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Write data to memory
    ret = mBlockDevice->program(mBlock.data(), mParams.downloadedBytes, mBlock.size());
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device program failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate,
                    "Secondary slot program with offset: "
                    "0x%" PRIx64,
                    mParams.downloadedBytes);
    mParams.downloadedBytes += mBlock.size();

    return ret;
}

} // namespace chip
