/*
 *
 * Copyright 2021, 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.
 */

#pragma once

#include <android-base/logging.h>
#include <android/hardware/confirmationui/1.0/types.h>
#include <android/hardware/keymaster/4.0/types.h>

#include <condition_variable>
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
#include <tuple>
#include <vector>

#include "common/libs/concurrency/thread_safe_queue.h"
#include "common/libs/confui/confui.h"
#include "common/libs/fs/shared_fd.h"

namespace android {
namespace hardware {
namespace confirmationui {
namespace V1_0 {
namespace implementation {
class GuestSession {
  public:
    using ConfUiMessage = cuttlefish::confui::ConfUiMessage;
    using ConfUiAckMessage = cuttlefish::confui::ConfUiAckMessage;
    using Queue = cuttlefish::ThreadSafeQueue<std::unique_ptr<ConfUiMessage>>;
    using QueueImpl = Queue::QueueImpl;

    enum class ListenerState : uint32_t {
        None = 0,
        Starting = 1,
        SetupDone = 2,
        Interactive = 3,
        Terminating = 4,
    };

    GuestSession(const std::uint32_t session_id, ListenerState& listener_state,
                 std::mutex& listener_state_lock, std::condition_variable& listener_state_condv,
                 cuttlefish::SharedFD host_fd, const teeui::MsgString& promptText,
                 const teeui::MsgVector<uint8_t>& extraData, const teeui::MsgString& locale,
                 const teeui::MsgVector<teeui::UIOption>& uiOptions)
        : prompt_text_{promptText.begin(), promptText.end()}, extra_data_{extraData.begin(),
                                                                          extraData.end()},
          locale_{locale.begin(), locale.end()}, ui_options_{uiOptions.begin(), uiOptions.end()},
          listener_state_(listener_state), listener_state_lock_(listener_state_lock),
          listener_state_condv_(listener_state_condv), host_fd_{host_fd},
          session_name_(MakeName(session_id)),
          incoming_msg_queue_(
              20, [this](GuestSession::QueueImpl* impl) { return QueueFullHandler(impl); }) {}

    ~GuestSession() {
        // the thread for PromptUserConfirmation is still alive
        // the host_fd_ may be alive
        auto state = listener_state_;
        if (state == ListenerState::SetupDone || state == ListenerState::Interactive) {
            Abort();
        }
        // TODO(kwstephenkim): close fd once Session takes the ownership of fd
        // join host_cmd_fetcher_thread_ once Session takes the ownership of fd
    }

    using ResultTriple =
        std::tuple<ResponseCode, teeui::MsgVector<uint8_t>, teeui::MsgVector<uint8_t>>;
    ResultTriple PromptUserConfirmation();

    Return<ResponseCode> DeliverSecureInputEvent(
        const ::android::hardware::keymaster::V4_0::HardwareAuthToken& secureInputToken);

    Return<void> Abort();
    std::string GetSessionId() const { return session_name_; }

    void Push(std::unique_ptr<ConfUiMessage>&& msg) { incoming_msg_queue_.Push(std::move(msg)); }

  private:
    template <typename F, typename... Args>
    bool SerializedSend(F&& f, cuttlefish::SharedFD fd, Args&&... args) {
        if (!fd->IsOpen()) {
            return false;
        }
        std::unique_lock<std::mutex> lock(send_serializer_mtx_);
        return f(fd, std::forward<Args>(args)...);
    }

    void QueueFullHandler(QueueImpl* queue_impl) {
        if (!queue_impl) {
            LOG(ERROR) << "Registered queue handler is "
                       << "seeing nullptr for queue implementation.";
            return;
        }
        const auto n = (queue_impl->size()) / 2;
        // pop front half
        queue_impl->erase(queue_impl->begin(), queue_impl->begin() + n);
    }

    std::string MakeName(const std::uint32_t i) const {
        return "ConfirmationUiSession" + std::to_string(i);
    }
    std::string prompt_text_;
    std::vector<std::uint8_t> extra_data_;
    std::string locale_;
    std::vector<teeui::UIOption> ui_options_;

    /*
     * lister_state_lock_ coordinates multiple threads that may
     * call the three Confirmation UI HAL APIs concurrently
     */
    ListenerState& listener_state_;
    std::mutex& listener_state_lock_;
    std::condition_variable& listener_state_condv_;
    cuttlefish::SharedFD host_fd_;

    const std::string session_name_;
    Queue incoming_msg_queue_;

    /*
     * multiple threads could try to write on the vsock at the
     * same time. E.g. promptUserConfirmation() thread sends
     * a command while abort() is being called. The abort() thread
     * will try to write an abort command concurrently.
     */
    std::mutex send_serializer_mtx_;
};
}  // namespace implementation
}  // namespace V1_0
}  // namespace confirmationui
}  // namespace hardware
}  // namespace android
