/*
 * 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 DRM_CONNECTOR_H
#define DRM_CONNECTOR_H
#include <string>
#include <unordered_map>
#include <vector>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "drm_encoder.h"
#include "hdi_device_common.h"
#include "hdi_shared_fd.h"

namespace OHOS {
namespace HDI {
namespace DISPLAY {
const std::string PROP_DPMS = "DPMS";
const std::string PROP_CRTCID = "CRTC_ID";
const std::string PROP_BRIGHTNESS = "brightness";
class DrmDevice;
class DrmModeBlock;

class DrmMode {
public:
    DrmMode() {};
    DrmMode(drmModeModeInfo &modeInfo, uint32_t id) : mModeInfo(modeInfo), mId(id) {}
    virtual ~DrmMode() {};
    drmModeModeInfoPtr GetModeInfoPtr()
    {
        return &mModeInfo;
    }
    void ConvertToHdiMode(DisplayModeInfo &hdiMode);

private:
    drmModeModeInfo mModeInfo = { 0 };
    int32_t mId = -1;
};

class DrmModeBlock {
public:
    explicit DrmModeBlock(DrmMode &mode);
    virtual ~DrmModeBlock();
    int32_t Init(DrmMode &mode);
    uint32_t GetBlockId() const
    {
        return mBlockId;
    }

private:
    uint32_t mBlockId = DRM_INVALID_ID;
};

class DrmConnector {
public:
    DrmConnector(drmModeConnector c, FdPtr &fd);
    virtual ~DrmConnector() {};
    uint32_t GetId() const
    {
        return mId;
    }
    uint32_t GetEncoderId() const
    {
        return mEncoderId;
    }
    void SetEncoderId(uint32_t id)
    {
        mEncoderId = id;
    }
    void GetDisplayCap(DisplayCapability &cap);
    int32_t Init(DrmDevice &drmDevice);
    int32_t PickIdleCrtcId(IdMapPtr<DrmEncoder> &encoders, IdMapPtr<DrmCrtc> &crtcs, uint32_t &crtcId);
    int32_t GetDisplaySupportedModes(uint32_t *num, DisplayModeInfo *modes);
    int32_t GetPreferenceId() const
    {
        return mPreferenceId;
    }
    uint32_t GetPropCrtcId() const
    {
        return mPropCrtcId;
    }
    int32_t TryPickEncoder(IdMapPtr<DrmEncoder> &encoders, uint32_t encoderId, IdMapPtr<DrmCrtc> &crtcs,
        uint32_t &crtcId);
    // update modes will reset the preference mode id and active mode id
    int32_t UpdateModes();
    std::unique_ptr<DrmModeBlock> GetModeBlockFromId(int32_t id);
    int32_t GetModeFromId(int32_t id, DrmMode &mode);
    uint64_t GetDpmsState() const
    {
        return mDpmsState;
    }
    int32_t SetDpmsState(uint64_t dmps);
    bool IsConnected();
    bool HandleHotplug(IdMapPtr<DrmEncoder> &encoders, IdMapPtr<DrmCrtc> &crtcs, bool plugIn);
    std::shared_ptr<DrmCrtc> UpdateCrtcId(IdMapPtr<DrmEncoder> &encoders, IdMapPtr<DrmCrtc> &crtcs,
        bool plugIn, drmModeConnectorPtr c, int *crtc_id);
    int32_t GetBrightness(uint32_t& level);
    int32_t SetBrightness(uint32_t level);

private:
    static void ConvertTypeToName(uint32_t type, std::string &name);
    static void ConvertToHdiType(uint32_t type, InterfaceType &hdiType);

    void InitModes(drmModeConnector c);
    uint32_t mId;
    InterfaceType mType;
    uint32_t mPhyWidth;
    uint32_t mPhyHeight;
    uint32_t mSupportLayers = 0;
    uint32_t mVirtualDispCount = 0;
    bool mSupportWriteBack = false;
    uint32_t mPropertyCount = 0;
    uint32_t mEncoderId;
    std::vector<uint32_t> mPossibleEncoders;
    std::string mName;
    drmModeConnection mConnectState;
    uint32_t mPropDpmsId = DRM_INVALID_ID;
    uint64_t mDpmsState = 0;
    uint32_t mPropCrtcId = DRM_INVALID_ID;
    uint32_t mPropBrightnessId = DRM_INVALID_ID;
    uint32_t mBrightnessLevel = 0;
    std::unordered_map<int32_t, DrmMode> mModes;
    int32_t mPreferenceId = INVALID_MODE_ID;

    FdPtr mDrmFdPtr;
};
} // namespace OHOS
} // namespace HDI
} // namespace DISPLAY
#endif // DRM_CONNECTOR_H