/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * 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.
 */

#ifndef SERVICES_INCLUDE_CLIENT_GROUP_H
#define SERVICES_INCLUDE_CLIENT_GROUP_H

#include <map>
#include <utility>

#include "input_client_info.h"
#include "input_death_recipient.h"

namespace OHOS {
namespace MiscServices {
class ClientGroup {
public:
    using ClientDiedHandler = std::function<void(const sptr<IInputClient> &)>;
    ClientGroup(uint64_t displayGroupId, ClientDiedHandler diedHandler)
        : displayGroupId_(displayGroupId), clientDiedHandler_(std::move(diedHandler))
    {
    }

    uint64_t GetDisplayGroupId();
    int32_t AddClientInfo(const sptr<IRemoteObject> &inputClient, const InputClientInfo &clientInfo);
    void RemoveClientInfo(const sptr<IRemoteObject> &client);
    void UpdateClientInfo(const sptr<IRemoteObject> &client,
        const std::unordered_map<UpdateFlag, std::variant<bool, uint32_t, ImeType, ClientState, TextTotalConfig,
            ClientType, pid_t, std::shared_ptr<BindImeData>, uint64_t, RequestKeyboardReason>> &updateInfos);

    std::shared_ptr<InputClientInfo> GetClientInfo(sptr<IRemoteObject> inputClient);
    std::shared_ptr<InputClientInfo> GetClientInfo(pid_t pid);
    std::shared_ptr<InputClientInfo> GetClientInfoByBindIme(pid_t bindImePid);
    std::shared_ptr<InputClientInfo> GetClientInfoByHostPid(pid_t hostPid);
    std::shared_ptr<InputClientInfo> GetClientInfoBoundRealIme();
    std::shared_ptr<InputClientInfo> GetCurrentClientInfoBoundRealIme();
    std::shared_ptr<InputClientInfo> GetCurrentClientInfo();
    std::shared_ptr<InputClientInfo> GetClientBoundImeByWindowId(uint32_t windowId);
    int64_t GetCurrentClientPid();
    int64_t GetInactiveClientPid();

    bool IsClientExist(sptr<IRemoteObject> inputClient);
    std::tuple<bool, uint64_t, bool> IsNotifyInputStop(const sptr<IInputClient> &client);

    sptr<IInputClient> GetCurrentClient();
    void SetCurrentClient(sptr<IInputClient> client);
    sptr<IInputClient> GetInactiveClient();
    void SetInactiveClient(sptr<IInputClient> client);

    bool IsCurClientFocused(int32_t pid, int32_t uid);
    bool IsCurClientUnFocused(int32_t pid, int32_t uid);

private:
    std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> GetClientMap();
    bool IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest);
    void OnClientDied(sptr<IInputClient> remote);
    uint64_t displayGroupId_{ DEFAULT_DISPLAY_ID };
    std::recursive_mutex mtx_;
    std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> mapClients_;

    std::mutex currentClientLock_{};
    sptr<IInputClient> currentClient_; // the current input client

    std::mutex inactiveClientLock_{};
    sptr<IInputClient> inactiveClient_; // the inactive input client

    std::mutex clientDiedLock_{};
    ClientDiedHandler clientDiedHandler_;
};
} // namespace MiscServices
} // namespace OHOS
#endif // SERVICES_INCLUDE_CLIENT_GROUP_H