/*
 * Copyright (C) 2021-2023 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 FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H
#define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <ctime>
#include <mutex>
#include <thread>
#include <variant>

#include "block_queue.h"
#include "controller_listener.h"
#include "element_name.h"
#include "want.h"
#include "event_handler.h"
#include "global.h"
#include "iinput_method_agent.h"
#include "iinput_method_system_ability.h"
#include "imc_inner_listener.h"
#include "ime_event_listener.h"
#include "input_client_info.h"
#include "input_method_property.h"
#include "input_method_status.h"
#include "input_method_utils.h"
#include "inputmethod_message_handler.h"
#include "ipc_skeleton.h"
#include "iremote_object.h"
#include "key_event.h"
#include "key_event_result_handler.h"
#include "msg_handler_callback_interface.h"
#include "panel_info.h"
#include "private_command_interface.h"
#include "visibility.h"

namespace OHOS {
namespace MiscServices {
class OnTextChangedListener : public virtual RefBase {
public:
    virtual ~OnTextChangedListener() {}
    virtual void InsertText(const std::u16string &text) = 0;
    virtual void DeleteForward(int32_t length) = 0;
    virtual void DeleteBackward(int32_t length) = 0;
    virtual void SendKeyEventFromInputMethod(const KeyEvent &event) = 0;
    virtual void SendKeyboardStatus(const KeyboardStatus &keyboardStatus) = 0;
    virtual void NotifyPanelStatusInfo(const PanelStatusInfo &info)
    {
    }
    virtual void NotifyKeyboardHeight(uint32_t height)
    {
    }
    virtual void SendFunctionKey(const FunctionKey &functionKey) = 0;
    virtual void SetKeyboardStatus(bool status) = 0;
    virtual void MoveCursor(const Direction direction) = 0;
    virtual void HandleSetSelection(int32_t start, int32_t end) = 0;
    virtual void HandleExtendAction(int32_t action) = 0;
    virtual void HandleSelect(int32_t keyCode, int32_t cursorMoveSkip) = 0;
    virtual std::u16string GetLeftTextOfCursor(int32_t number) = 0;
    virtual std::u16string GetRightTextOfCursor(int32_t number) = 0;
    virtual int32_t GetTextIndexAtCursor() = 0;
    virtual int32_t ReceivePrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
    {
        return ErrorCode::NO_ERROR;
    }
    /**
     * @brief Set preview text.
     *
     * When InputMethod app sends request to set preview text, the function will be called.
     *
     * @param text Indicates the text to be previewed.
     * @param range Indicates the range of text to be replaced.
     * @return
     *     If success, please return 0.
     *     If parameter range check error, please return -1.
     *     If other failure, no specific requirement.
     * @since 12
     */
    virtual int32_t SetPreviewText(const std::u16string &text, const Range &range)
    {
        return ErrorCode::NO_ERROR;
    }
    /**
     * @brief Finish text preview.
     *
     * When InputMethod app sends request to finish text preview, the function will be called.
     *
     * @since 12
     */
    virtual void FinishTextPreview()
    {
    }
    virtual void OnDetach()
    {
    }
    /**
     * @brief Is listener from ts registration.
     *
     * If you use C/C++ interface, ignore this.
     *
     * @since 12
     */
    virtual bool IsFromTs()
    {
        return false;
    }
    virtual std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler()
    {
        return nullptr;
    }

private:
    friend class InputMethodController;
    void InsertTextV2(const std::u16string &text);
    void DeleteForwardV2(int32_t length);
    void DeleteBackwardV2(int32_t length);
    void SendKeyboardStatusV2(const KeyboardStatus &keyboardStatus);
    void SendFunctionKeyV2(const FunctionKey &functionKey);
    void MoveCursorV2(const Direction &direction);
    void HandleExtendActionV2(int32_t action);
    std::u16string GetLeftTextOfCursorV2(int32_t number);
    std::u16string GetRightTextOfCursorV2(int32_t number);
    int32_t GetTextIndexAtCursorV2();
    void SendKeyEventFromInputMethodV2(const KeyEvent &event);
    void NotifyPanelStatusInfoV2(const PanelStatusInfo &info);
    void NotifyKeyboardHeightV2(uint32_t height);
    void SetKeyboardStatusV2(bool status);
    void HandleSetSelectionV2(int32_t start, int32_t end);
    void HandleSelectV2(int32_t keyCode, int32_t cursorMoveSkip);
    int32_t ReceivePrivateCommandV2(const std::unordered_map<std::string, PrivateDataValue> &privateCommand);
    int32_t SetPreviewTextV2(const std::u16string &text, const Range &range);
    void FinishTextPreviewV2();
    void OnDetachV2();
};
using PrivateDataValue = std::variant<std::string, bool, int32_t>;
using KeyEventCallback = std::function<void(std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed)>;
using WindowScaleCallback = std::function<int32_t(uint32_t windowId, CursorInfo &cursorInfo)>;
class InputMethodController : public RefBase, public PrivateCommandInterface {
public:
    /**
     * @brief Get the instance of InputMethodController.
     *
     * This function is used to get the instance of InputMethodController.
     *
     * @return The instance of InputMethodController.
     * @since 6
     */
    IMF_API static sptr<InputMethodController> GetInstance();

    /**
     * @brief Show soft keyboard, set listener and bind IMSA with default states and attribute.
     *
     * This function is used to show soft keyboard,  set listener and bind IMSA,
     * default state is 'true', default attribute is 'InputAttribute::PATTERN_TEXT'.
     *
     * @param listener Indicates the listener in order to manipulate text.
     * @param type Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t Attach(sptr<OnTextChangedListener> listener, ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Set listener and bind IMSA with given states and default attribute.
     *
     * This function is used to set listener and bind IMSA,
     * default attribute is 'InputAttribute::PATTERN_TEXT'. Show soft keyboard when state is true.
     *
     * @param listener          Indicates the listener in order to manipulate text.
     * @param isShowKeyboard    Indicates the state, if you want to show soft keyboard, please pass in true.
     * @param type              Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 8
     */
    IMF_API int32_t Attach(
        sptr<OnTextChangedListener> listener, bool isShowKeyboard, ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Set listener and bind IMSA with given states and attribute.
     *
     * This function is used to set listener and bind IMSA.
     * Show soft keyboard when state is true, and customized attribute.
     *
     * @param listener          Indicates the listener in order to manipulate text.
     * @param isShowKeyboard    Indicates the state, if you want to show soft keyboard, please pass in true.
     * @param attribute         Indicates the attribute, such as input pattern, enter eyType, input option.
     * @param type              Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 8
     */
    IMF_API int32_t Attach(sptr<OnTextChangedListener> listener, bool isShowKeyboard, const InputAttribute &attribute,
        ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Set listener and bind IMSA with given states and textConfig.
     *
     * This function is used to set listener and bind IMSA.
     * Show soft keyboard when state is true, and customized attribute.
     *
     * @param listener          Indicates the listener in order to manipulate text.
     * @param isShowKeyboard    Indicates the state, if you want to show soft keyboard, please pass in true.
     * @param textConfig        Indicates the textConfig, such as input attribute, cursorInfo, range of text selection,
     *                          windowId.
     * @param type              Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    IMF_API int32_t Attach(sptr<OnTextChangedListener> listener, bool isShowKeyboard, const TextConfig &textConfig,
        ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Set listener and bind IMSA with given states and textConfig.
     *
     * This function is used to set listener and bind IMSA.
     * Show soft keyboard when state is true, and customized attribute.
     *
     * @param listener                  Indicates the listener in order to manipulate text.
     * @param attachOptions             Indicates the attachOptions, if you want to show soft keyboard,
     *                                  please pass in true.
     * @param textConfig                Indicates the textConfig, such as input attribute, cursorInfo, range of
     *                                  text selection,windowId.
     * @param type                      Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t Attach(sptr<OnTextChangedListener> listener, const AttachOptions &attachOptions,
        const TextConfig &textConfig, ClientType type = ClientType::INNER_KIT);
    /**
     * @brief Show soft keyboard.
     *
     * This function is used to show soft keyboard of current client.
     *
     * @param type   Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ShowTextInput(ClientType type = ClientType::INNER_KIT);
    /**
     * @brief Show soft keyboard.
     *
     * This function is used to show soft keyboard of current client.
     *
     * @param attachOptions   Indicates the attachOptions, such as requestKeyboardReason
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t ShowTextInput(const AttachOptions &attachOptions, ClientType type = ClientType::INNER_KIT);
    /**
     * @brief Hide soft keyboard.
     *
     * This function is used to hide soft keyboard of current client, and keep binding.
     *
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t HideTextInput();

    /**
     * @brief Hide current input method, clear text listener and unbind IMSA.
     *
     * This function is used to stop input, whick will set listener to nullptr,
     * hide current soft keyboard and unbind IMSA.
     *
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t Close();

    /**
     * @brief Hide current input method, clear text listener and unbind IMSA.
     *
     * This function is used to stop input, whick will set listener to nullptr,
     * hide current soft keyboard and unbind IMSA.
     *
     * @param clientSessionId Indicates the client session ID for tracking, -1 means not specified.
     * @return Returns 0 for success, others for failure.
     * @since 26
     */
    IMF_API int32_t Close(int32_t clientSessionId);

    /**
     * @brief A callback function when the cursor changes.
     *
     * This function is the callback when the cursor changes.
     *
     * @param cursorInfo Indicates the information of current cursor changes.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t OnCursorUpdate(CursorInfo cursorInfo);

    /**
     * @brief Discard the typing text.
     *
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t DiscardTypingText();

    /**
     * @brief A callback function when the cursor changes.
     *
     * This function is the callback when the cursor changes.
     *
     * @param text  Indicates the currently selected text.
     * @param start Indicates the coordinates of the current start.
     * @param end   Indicates the coordinates of the current end.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t OnSelectionChange(std::u16string text, int start, int end);

    /**
     * @brief Changing the configuration of soft keyboard.
     *
     * This function is used to change the configuration of soft keyboard.
     *
     * @param info Indicates the current configuration.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t OnConfigurationChange(Configuration info);
    IMF_API void SetControllerListener(std::shared_ptr<ControllerListener> controllerListener);

    /**
     * @brief Dispatch keyboard event.
     *
     * This function is used to Dispatch events of keyboard.
     *
     * @param keyEvent Indicates the events keyboard.
     * @return Returns true for success otherwise for failure.
     * @since 6
     */
    /**
     * @brief Dispatch keyboard event.
     *
     * This function is used to Dispatch events of keyboard.
     *
     * @param keyEvent Indicates the events keyboard.
     * @param callback Indicates the consumption result of key event.
     * @return Returns 0 for success, others for failure.
     * @since 11
     */
    IMF_API int32_t DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventCallback callback);

    /**
     * @brief List input methods.
     *
     * This function is used to list all of input methods.
     *
     * @param props Indicates the input methods that will be listed.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ListInputMethod(std::vector<Property> &props,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief List input methods.
     *
     * This function is used to list enabled or disabled input methods.
     *
     * @param props     Indicates the input methods that will be listed.
     * @param enable    Indicates the state of input method.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ListInputMethod(bool enable, std::vector<Property> &props,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief List input method subtypes.
     *
     * This function is used to list specified input method subtypes.
     *
     * @param property      Indicates the specified input method property.
     * @param subProperties Indicates the subtypes of specified input method that will be listed.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProperties,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief List current input method subtypes.
     *
     * This function is used to list current input method subtypes.
     *
     * @param subProperties Indicates the subtypes of current input method that will be listed.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProperties,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Get enter key type.
     *
     * This function is used to get enter key type of current client.
     *
     * @param keyType Indicates the enter key type of current client that will be obtained, such as SEND, SEARCH...
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    int32_t GetEnterKeyType(int32_t &keyType);

    /**
     * @brief Get input pattern.
     *
     * This function is used to get text input type of current client.
     *
     * @param inputPattern Indicates the text input type of current client that will be obtained, such as TEXT, URL...
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    int32_t GetInputPattern(int32_t &inputPattern);

    /**
     * @brief Get text config.
     *
     * This function is used to get text config of current client.
     *
     * @param textConfig Indicates the text config of current client that will be obtained.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t GetTextConfig(TextTotalConfig &config);

    /**
     * @brief Get cursor info.
     *
     * This function is used to get cursor info of current client.
     *
     * @param cursorInfo Indicates the cursor info of current client that will be obtained.
     * @param userId Indicates the user id.
     * @return Returns 0 for success, others for failure.
     * @since 12
     */
    IMF_API int32_t GetCursorInfo(CursorInfo &cursorInfo, int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Get current input method property.
     *
     * This function is used to get current input method property.
     *
     * @return The property of current input method.
     * @since 6
     */
    IMF_API std::shared_ptr<Property> GetCurrentInputMethod(int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Get current input method subtypes.
     *
     * This function is used to get current input method's current subtype.
     *
     * @return The subtypes of current input method.
     * @since 6
     */
    IMF_API std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype(int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Get default input method property.
     *
     * This function is used to get default input method property.
     *
     * @return The property of default input method.
     * @since 10
     */
    IMF_API int32_t GetDefaultInputMethod(std::shared_ptr<Property> &prop,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief get input method config ability.
     *
     * This function is used to get input method config ability.
     *
     * @return The info of input settings.
     * @since 10
     */
    IMF_API int32_t GetInputMethodConfig(AppExecFwk::ElementName &inputMethodConfig,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Is keyboard calling process.
     *
     * This function is used to get is keyboard calling process for pid.
     *
     * @param pid Indicates the process id.
     * @return Returns true or false.
     * @since 20
     */
    IMF_API bool IsKeyboardCallingProcess(int32_t pid, uint32_t windowId);

    /**
     * @brief Set calling window id.
     *
     * This function is used to set calling window id to input method.
     *
     * @param windowId Indicates the window id.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t SetCallingWindow(uint32_t windowId);

    /**
     * @brief Switch input method or subtype.
     *
     * This function is used to switch input method or subtype.
     *
     * @param name      Indicates the id of target input method.
     * @param subName   Optional parameter. Indicates the subtype of target input method.
     * @return Returns 0 for success, others for failure.
     * @since 11
     */
    IMF_API int32_t SwitchInputMethod(SwitchTrigger trigger, const std::string &name, const std::string &subName = "",
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Set EDC backup input method configuration
     *
     * This function is used to configure EDC backup input method.
     * Requires system-level permission.
     *
     * @param edcBackupImeName Indicates the EDC backup input method name (Input method B).
     * @return Returns 0 for success, others for failure.
     * @since 26
     */
    IMF_API int32_t SetEDCDefaultInputMethod(const std::string &edcBackupImeName);

    /**
     * @brief Set simple keyboard mode.
     *
     * This function is used to set the simple keyboard mode.
     *
     * @param enable   indicates enable simple keyboard or not.
     * @return Returns 0 for success, others for failure.
     * @since 20
     */
    IMF_API int32_t SetSimpleKeyboardEnabled(bool enable);

    /**
     * @brief Show soft keyboard.
     *
     * This function is used to show soft keyboard of current client that is in the default display group.
     *
     * @param type   Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t ShowSoftKeyboard(ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Show soft keyboard.
     *
     * This function is used to show the soft keyboard of the current client that is showing in the target displayId
     *
     * @param displayId Indicates the target displayId.
     * @param type   Indicates the type of caller.
     * @return Returns 0 for success, others for failure.
     * @since 23
     */
    IMF_API int32_t ShowSoftKeyboard(uint64_t displayId, ClientType type = ClientType::INNER_KIT);

    /**
     * @brief Hide soft keyboard.
     *
     * This function is used to hide soft keyboard of current client that is in the default display group
     * and keep binding.
     *
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t HideSoftKeyboard();

    /**
     * @brief Hide soft keyboard.
     *
     * This function is used to hide soft keyboard of current client that is showing in the target displayId,
     * and keep binding.
     *
     * @param displayId Indicates the target displayId.
     * @return Returns 0 for success, others for failure.
     * @since 23
     */
    IMF_API int32_t HideSoftKeyboard(uint64_t displayId);

    /**
     * @brief Stop current input session.
     *
     * This function is used to stop current input session.
     *
     * @return Returns 0 for success, others for failure.
     * @since 6
     */
    IMF_API int32_t StopInputSession();

    /**
     * @brief Show input method setting extension dialog.
     *
     * This function is used to show input method setting extension dialog.
     *
     * @return Returns 0 for success, others for failure.
     * @since 8
     */
    IMF_API int32_t ShowOptionalInputMethod();

    // Deprecated innerkits with no permission check, kept for compatibility

    /**
     * @brief Show soft keyboard.
     *
     * This function is used to show soft keyboard of current client.
     *
     * @return Returns 0 for success, others for failure.
     * @deprecated since 9
     * @since 6
     */
    IMF_API int32_t ShowCurrentInput();

    /**
     * @brief Hide soft keyboard.
     *
     * This function is used to hide soft keyboard of current client, and keep binding.
     *
     * @return Returns 0 for success, others for failure.
     * @deprecated since 9
     * @since 6
     */
    IMF_API int32_t HideCurrentInput();

    /**
     * @brief Request to hide input method.
     *
     * This function is used to request to hide input method.
     *
     * @param callingWndId Indicates the id of the window which caller in.
     * @param isFocusTriggered Indicates the caller is focused or not.
     * @param displayId Indicates the id of the the display which caller in.
     * @return Returns 0 for success, others for failure.
     * @since 11
     */
    IMF_API int32_t RequestHideInput(uint32_t callingWndId = 0, bool isFocusTriggered = false, uint64_t displayId = 0,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Show input method setting extension dialog.
     *
     * This function is used to show input method setting extension dialog.
     *
     * @return Returns 0 for success, others for failure.
     * @deprecated since 9
     * @since 6
     */
    IMF_API int32_t DisplayOptionalInputMethod();

    /**
     * @brief Get attach status.
     *
     * This function is used to get status of attach.
     *
     * @return Returns true for attached otherwise for detached.
     * @since 10
     */
    IMF_API bool WasAttached();

    /**
     * @brief Set agent which will be used to communicate with IMA.
     *
     * This function is used to Set agent.
     *
     * @since 10
     */
    void OnInputReady(sptr<IRemoteObject> agentObject, const BindImeInfo &imeInfo);

    /**
     * @brief Unbind IMC with Service.
     *
     * This function is unbind imc with service.
     *
     * @since 10
     */
    void OnInputStop(bool isStopInactiveClient = false, const sptr<IRemoteObject> &proxy = nullptr,
        bool isSendKeyboardStatus = true, bool isStopByMultiPreemptInProc = false);
    void OnImeMirrorStop(sptr<IRemoteObject> object);

    /**
     * @brief Insert text.
     *
     * This function is used to insert text into editor.
     *
     * @param text Indicates the text which will be inserted.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t InsertText(const std::u16string &text);

    /**
     * @brief Move cursor.
     *
     * This function is used to move cursor according to the direction.
     *
     * @param direction Indicates the direction according to which the cursor will be moved.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t MoveCursor(Direction direction);

    /**
     * @brief Delete forward.
     *
     * This function is used to delete text at the left of cursor.
     *
     * @param length Indicates the length of deleted text.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t DeleteForward(int32_t length);

    /**
     * @brief Delete backward.
     *
     * This function is used to delete text at the right of cursor.
     *
     * @param length Indicates the length of deleted text.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t DeleteBackward(int32_t length);

    /**
     * @brief Get text at the left of cursor.
     *
     * This function is used to get text at the left of cursor.
     *
     * @param length Indicates the length of text.
     * @param text Indicates the text which will be get.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t GetLeft(int32_t length, std::u16string &text);

    /**
     * @brief Get text at the right of cursor.
     *
     * This function is used to get text at the right of cursor.
     *
     * @param length Indicates the length of text.
     * @param text Indicates the text which will be get.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t GetRight(int32_t length, std::u16string &text);

    /**
     * @brief Select text in editor by range.
     *
     * This function is used to select text in editor by range.
     *
     * @param start Indicates the beginning of the range.
     * @param start Indicates the end of the range.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    void SelectByRange(int32_t start, int32_t end);

    /**
     * @brief Select text in editor by cursor movement.
     *
     * This function is used to select text in editor by cursor movement.
     *
     * @param direction Indicates the direction of cursor movement.
     * @param cursorMoveSkip Indicates the skip of cursor movement.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    void SelectByMovement(int32_t direction, int32_t cursorMoveSkip);

    /**
     * @brief Handle extend action code.
     *
     * This function is used to handle extend action code.
     *
     * @param action Indicates the action code which will be handled.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t HandleExtendAction(int32_t action);

    /**
     * @brief Get the index number of text at cursor.
     *
     * This function is used to get the index number of text at cursor.
     *
     * @param index Indicates the index number of text at cursor.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t GetTextIndexAtCursor(int32_t &index);

    /**
     * @brief Send keyboard status.
     *
     * This function is used to send keyboard status to editor.
     *
     * @param status Indicates the status of keyboard.
     * @since 10
     */
    void SendKeyboardStatus(KeyboardStatus status);

    /**
     * @brief Send panel status info.
     *
     * This function is used to send panel status info to editor.
     * Only notify the status info of soft keyboard(not contain candidate column) at present
     *
     * @param info Indicates the status info of panel.
     * @since 11
     */
    void NotifyPanelStatusInfo(const PanelStatusInfo &info);

    /**
     * @brief Send panel height.
     *
     * This function is used to send panel height to editor.
     *
     * @param info Indicates the panel height.
     * @since 11
     */
    void NotifyKeyboardHeight(uint32_t height);

    /**
     * @brief Send function key.
     *
     * This function is used to send function key to editor.
     *
     * @param functionKey Indicates the function key.
     * @return Returns 0 for success, others for failure.
     * @since 10
     */
    int32_t SendFunctionKey(int32_t functionKey);

    /**
     * @brief Deactivate the input client.
     *
     * This function is used to deactivate the input client.
     *
     * @since 11
     */
    void DeactivateClient();

    /**
     * @brief Query whether an input type is supported.
     *
     * This function is used to query whether an input type is supported.
     *
     * @param type Indicates the input type being queried.
     * @return Returns true for supported, false for not supported.
     * @since 11
     */
    IMF_API bool IsInputTypeSupported(InputType type);

    /**
     * @brief Start the input method which provides the specific input type.
     *
     * This function is used to start the input method which provides the specific input type.
     *
     * @param type Indicates the input type being specified.
     * @return Returns 0 for success, others for failure.
     * @since 11
     */
    IMF_API int32_t StartInputType(InputType type, bool isPersistence = true);

    /**
     * @brief Start the input method which provides the specific input type.
     *
     * This function is used to start the input method which provides the specific input type.
     *
     * @param type Indicates the input type being specified.
     * @return Returns 0 for success, others for failure.
     * @since 21
     */
    IMF_API int32_t StartInputTypeAsync(InputType type, bool isPersistence = true);

    /**
     * @brief Query whether the specific type panel is shown.
     *
     * This function is used to query whether the specific type panel is shown in the default display group.
     *
     * @param panelInfo Indicates the info of the panel.
     * @param isShown Indicates the state of the specific panel.
     * @return Returns 0 for success, others for failure.
     * @since 11
     */
    IMF_API int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown);

    /**
     * @brief Query whether the specific type panel is shown.
     *
     * This function is used to query whether the specific type panel is shown in the target displayId.
     *
     * @param panelInfo Indicates the info of the panel.
     * @param isShown Indicates the state of the specific panel.
     * @param displayId Indicates the target displayId.
     * @return Returns 0 for success, others for failure.
     * @since 23
     */
    IMF_API int32_t IsPanelShown(uint64_t displayId, const PanelInfo &panelInfo, bool &isShown);

    int32_t UpdateListenEventFlag(uint32_t finalEventFlag, uint32_t eventFlag, bool isOn);

    /**
     * @brief Send private command to ime.
     *
     * This function is used to send private command to ime.
     *
     * @param privateCommand Indicates the private command which will be send.
     * @return Returns 0 for success, others for failure.
     * @since 12
     */
    IMF_API int32_t SendPrivateCommand(
        const std::unordered_map<std::string, PrivateDataValue> &privateCommand,
        bool validateDefaultIme = true) override;

    /**
     * @brief Receive private command from ime.
     *
     * This function is used to receive private command from ime.
     *
     * @param privateCommand Indicates the private command which send from ime.
     * @return Returns 0 for success, others for failure.
     * @since 12
     */
    int32_t ReceivePrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand) override;

    /**
     * @brief Set preview text.
     *
     * This function is used to set preview text.
     *
     * @param text Indicates the text to be previewed.
     * @param range Indicates the range of text to be replaced.
     * @return Returns 0 for success, others for failure.
     * @since 12
     */
    int32_t SetPreviewText(const std::string &text, const Range &range);

    /**
     * @brief Finish text preview.
     *
     * This function is used to finish text preview.
     *
     * @since 12
     */
    int32_t FinishTextPreview();

    /**
     * @brief Query whether an process id current inputmethod.
     *
     * This function is used to query whether an process id is inputmethod.
     *
     * @param type Indicates current process id.
     * @return Returns true for current ime process id, false for not current ime process id.
     * @since 12
     */
    IMF_API bool IsCurrentImeByPid(int32_t pid, int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Reset controller.
     *
     * This function is used to reset controller.
     * Do not call this interface unless you know what you are doing
     *
     * @since 12
     */
    IMF_API void Reset();

    /**
     * @brief Query whether the default input method is setting.
     *
     * This function is used to query whether the default input method is setting.
     * Do not call this interface unless you know what you are doing
     *
     * @since 13
     */
    IMF_API bool IsDefaultImeSet(int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Enable the ime called bundleName.
     *
     * This function is used to enable the ime called bundleName.
     * Do not call this interface unless you know what you are doing
     *
     * @since 13
     */
    IMF_API int32_t EnableIme(const std::string &bundleName, const std::string &extensionName = "",
        EnabledStatus status = EnabledStatus::BASIC_MODE, int32_t userId = ImfCommonConst::DEFAULT_USER_ID);

    /**
     * @brief Send ArrayBuffer message to ime.
     *
     * This function is used to Send ArrayBuffer message to ime.
     *
     * @param arrayBuffer Indicates the ArrayBuffer message that will be send to the ime.
     *                    The member msgId limit 256B, and member msgParam limit 128KB.
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t SendMessage(const ArrayBuffer &arrayBuffer);
    int32_t RecvMessage(const ArrayBuffer &arrayBuffer);

    /**
     * @brief Regist message handler callback.
     *
     * This function is used to register a message handler to receive message from ime, or remove message handler.
     *
     * @param msgHandler Indicates the message handler callback.
     *                   If nullptr will remove callback that was registered and trigger function OnTerminated.
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler = nullptr);

    /**
     * @brief Get ime state.
     *
     * This function is used to get it's enabled state by ime.
     *
     * @param status Indicates the enabled state
     * @return Returns 0 for success, others for failure.
     * @since 16
     */
    IMF_API int32_t GetInputMethodState(EnabledStatus &status);

    IMF_API void ReportBaseTextOperation(int32_t eventCode, int32_t errCode);

    IMF_API void UpdateTextPreviewState(bool isSupport);

    /**
     * @brief Send Private Data.
     *
     * This function only available special service apply.
     *
     * @param privateCommand Indicates the private data information.
     * @return Returns 0 for success, others for failure.
     * @since 18
     */
    IMF_API int32_t SendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand);

    /**
     * @brief Registration callbacks are used for coordinate transformation processing in window zooming scenarios.
     *
     * This function only available special service apply.
     *
     * @param callback Indicates the window zooming handle callback
     * @return Returns 0 for success, others for failure.
     * @since 18
     */
    IMF_API int32_t RegisterWindowScaleCallbackHandler(WindowScaleCallback&& callback);

    /**
     * @brief Get the type of the current client.
     *
     * @param type Indicates the type of current client.
     * @return Returns 0 for success, others for failure.
     * @since 23
     */
    IMF_API int32_t GetClientType(ClientType &type);

    void HandleKeyEventResult(uint64_t cbId, bool consumeResult);

    IMF_API void SetImcInnerListener(const std::shared_ptr<ImcInnerListener> &imcInnerListener);

    int32_t GetCurrentCursorInfo(CursorInfo &cursorInfo);

    /**
     * @brief Get soft keyboard window info.
     *
     * This function is used to query the window info of the real ime.
     *
     * @param userId         Indicates the user id.
     * @param imeInfo  Indicates the soft keyboard info of the real ime。
     * if has no real ime process, the info is only contain status(InputWindowStatus::HIDE)
     * if the real ime is not bound, the info is only contain status(InputWindowStatus::HIDE)
     * if the real ime is bound, but has no soft keyboard, the info is only contain status(InputWindowStatus::HIDE)
     * @return Returns 0 for success, return others for failed.
     */
    IMF_API int32_t GetSoftKeyboardInfo(int32_t userId, BoundImeInfo &imeInfo);

private:
    friend class MockInputMethodSystemAbilityProxy;
    friend class ImeEventMonitorManagerImpl;
    InputMethodController();
    ~InputMethodController();

    int32_t Initialize();
    sptr<IInputMethodSystemAbility> GetSystemAbilityProxy(bool ifRetry = true);
    sptr<IInputMethodSystemAbility> TryGetSystemAbilityProxy();
    void RemoveDeathRecipient();
    int32_t StartInput(
        InputClientInfo &inputClientInfo, std::vector<sptr<IRemoteObject>> &agents, std::vector<BindImeInfo> &imeInfos);
    int32_t ShowInput(
        sptr<IInputClient> &client, ClientType type = ClientType::INNER_KIT, int32_t requestKeyboardReason = 0);
    int32_t HideInput(sptr<IInputClient> &client);
    int32_t ReleaseInput(sptr<IInputClient> &client, int32_t clientSessionId = -1);
    int32_t ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props,
        int32_t userId = ImfCommonConst::DEFAULT_USER_ID);
    int32_t AttachExec(sptr<OnTextChangedListener> listener, const AttachOptions &attachOptions,
        const TextConfig &textConfig, ClientType type);
    void ClearEditorCache(bool isNewEditor, sptr<OnTextChangedListener> lastListener);
    void OnRemoteSaDied(const wptr<IRemoteObject> &object);
    void RestoreListenInfoInSaDied();
    void RestoreClientInfoInSaDied();
    int32_t RestoreListenEventFlag();
    void SaveTextConfig(const TextConfig &textConfig);
    sptr<OnTextChangedListener> GetTextListener();
    void SetTextListener(sptr<OnTextChangedListener> listener);
    bool IsEditable();
    bool IsBound();
    void SetAgent(const sptr<IRemoteObject> &agentObject, const std::string &bundleName);
    std::shared_ptr<IInputMethodAgent> GetAgent();
    void PrintLogIfAceTimeout(int64_t start);
    void PrintTextChangeLog();
    void PrintKeyEventLog();
    std::shared_ptr<MsgHandlerCallbackInterface> GetMsgHandlerCallback();
    int32_t IsValidTextConfig(const TextConfig &textConfig);
    void SetBindImeInfo(const std::pair<int64_t, std::string> &imeInfo);
    std::pair<int64_t, std::string> GetBindImeInfo();
    int32_t SetPreviewTextInner(const std::string &text, const Range &range);
    int32_t ShowTextInputInner(const AttachOptions &attachOptions, ClientType type);
    int32_t ShowSoftKeyboardInner(ClientType type);
    int32_t ShowSoftKeyboardInner(uint64_t displayId, ClientType type);
    void ReportClientShow(int32_t eventCode, int32_t errCode, ClientType type);
    void GetWindowScaleCoordinate(uint32_t windowId, CursorInfo &cursorInfo);
    void CalibrateImmersiveParam(InputAttribute &inputAttribute, bool shouldOverrideImmersiveMode = false);
    void CalibrateInputPatternParam(InputAttribute &inputAttribute);
    bool IsDisableImmersiveMode();
    bool IsPcMode();
    bool IsSupportPcMode();
    bool IsDisablePcModeImmersiveMode();
    bool ShouldOverrideImmersiveMode(const TextConfig &textConfig);
    void ClearAgentInfo();
    int32_t SendRequestToAllAgents(std::function<int32_t(std::shared_ptr<IInputMethodAgent>)> task);
    int32_t SendRequestToImeMirrorAgent(std::function<int32_t(std::shared_ptr<IInputMethodAgent>)> task);
    void SetInputReady(const std::vector<sptr<IRemoteObject>> &agentObjects, const std::vector<BindImeInfo> &imeInfos);
    std::shared_ptr<ImcInnerListener> GetImcInnerListener();
    int32_t SetCallingWindowByIMSA(uint32_t windowId);
    void NotifyAttachFailure(int32_t errCode);
    bool SubscribeSaStart(std::function<void()> handler, int32_t saId);
    int32_t GetInputStartInfo(InputStartInfo &info);  // default displayId, foreground user
    std::shared_ptr<AppExecFwk::EventHandler> GetMainHandler();
    void OnTmpInputStop(const sptr<IRemoteObject> &proxy);

    struct CtrlEventInfo {
        std::chrono::steady_clock::time_point timestamp;
        std::string eventName;
        bool operator==(const CtrlEventInfo &info) const
        {
            return (timestamp == info.timestamp && eventName == info.eventName);
        }
    };

    static BlockQueue<CtrlEventInfo> ctrlEventQueue_;

    class QueueGuard {
    public:
        explicit QueueGuard(const std::string &name);
        ~QueueGuard();

    private:
        bool needPop_;
    };

    std::shared_ptr<ControllerListener> controllerListener_;
    std::mutex abilityLock_;
    sptr<IInputMethodSystemAbility> abilityManager_ = nullptr;
    sptr<InputDeathRecipient> deathRecipient_;

    struct AgentInfo {
        sptr<IRemoteObject> agentObject = nullptr;
        std::shared_ptr<IInputMethodAgent> agent = nullptr;
        ImeType imeType = ImeType::NONE;
    };
    std::mutex agentLock_;
    std::vector<AgentInfo> agentInfoList_;

    std::mutex textListenerLock_;
    sptr<OnTextChangedListener> textListener_ = nullptr;
    std::atomic_bool isDiedAttached_{ false };

    std::mutex cursorInfoMutex_;
    CursorInfo cursorInfo_;

    std::atomic_bool isTextNotified_{ false };
    std::mutex editorContentLock_;
    std::u16string textString_;
    int selectOldBegin_ = 0;
    int selectOldEnd_ = 0;
    int selectNewBegin_ = 0;
    int selectNewEnd_ = 0;

    static std::mutex instanceLock_;
    static sptr<InputMethodController> instance_;
    static std::shared_ptr<AppExecFwk::EventHandler> handler_;

    static std::mutex logLock_;
    static int keyEventCountInPeriod_;
    static std::chrono::system_clock::time_point startLogTime_;
    static std::mutex printTextChangeMutex_;
    static int32_t textChangeCountInPeriod_;
    static std::chrono::steady_clock::time_point textChangeStartLogTime_;

    std::atomic_bool isEditable_{ false };
    std::atomic_bool isBound_{ false };
    std::atomic_bool bootCompleted_{ false };

    std::recursive_mutex clientInfoLock_;
    InputClientInfo clientInfo_;

    static constexpr int CURSOR_DIRECTION_BASE_VALUE = 2011;
    std::atomic_bool isDiedRestoreListen_{ false };

    std::mutex textConfigLock_;
    TextConfig textConfig_;
    
    struct ImmersiveCache {
        std::atomic_bool isSupportPcModeCached{ false };
        std::atomic_bool isSupportPcModeQueried{ false };
        std::atomic_bool isDisablePcModeImmersiveModeCached{ false };
        std::atomic_bool isDisablePcModeImmersiveModeQueried{ false };
        std::atomic_bool isDisableImmersiveModeCached{ false };
        std::atomic_bool isDisableImmersiveModeQueried{ false };
        void ResetQueried()
        {
            isDisableImmersiveModeQueried.store(false);
            isSupportPcModeQueried.store(false);
            isDisablePcModeImmersiveModeQueried.store(false);
        }
    };
    ImmersiveCache immersiveCache_;

    struct KeyEventInfo {
        std::chrono::system_clock::time_point timestamp{};
        std::shared_ptr<MMI::KeyEvent> keyEvent;
        bool operator==(const KeyEventInfo &info) const
        {
            return (timestamp == info.timestamp && keyEvent == info.keyEvent);
        }
    };
    static constexpr int32_t MAX_WAIT_TIME = 5000;
    BlockQueue<KeyEventInfo> keyEventQueue_{ MAX_WAIT_TIME };

    std::mutex msgHandlerMutex_;
    std::shared_ptr<MsgHandlerCallbackInterface> msgHandler_ = nullptr;
    std::mutex bindImeInfoLock_;
    std::pair<int64_t, std::string> bindImeInfo_{ 0, "" }; // for hiSysEvent
    std::atomic_uint32_t sessionId_ { 0 };

    std::mutex windowScaleCallbackMutex_;
    WindowScaleCallback windowScaleCallback_ = nullptr;
    KeyEventResultHandler keyEventRetHandler_;
    std::mutex imcInnerListenerLock_;
    std::shared_ptr<ImcInnerListener> imcInnerListener_{ nullptr };
};
} // namespace MiscServices
} // namespace OHOS
#endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H