#pragma once

#include "processviewserver.h"
#include "rleventlogserver.h"
#include "rltime.h"
#include "rlcutil.h"
#include "rlsvganimator.h"
#include <math.h>
#include <map>
#include <unordered_map>
#include <vector>
#include <functional>

#include "PvStyle.h"
#include "common/Logger.h"

// 主窗口的 id 是 0，其它创建的控件都是主窗口的子控件，在创建子控件时，id 从 1 开始累加
#define PV_ID_MAIN 0
#define PV_ID_NUL -999

enum class EPvMaskID
{
    NUL = 0,
    LOGIN,
    HOME,
    Running,
    SysManage,
    Statistics,
};

enum class EPvCode
{
    NUL = 0,
    MASK_LOGIN,
    MASK_HOME,
    MASK_RUNNING,
    MASK_FORECAST,
    MASK_FORECAST_STORAGE,
    MASK_FORECAST_SOLAR,
    MASK_FORECAST_CHARGE,
    MASK_STAT,
    MASK_STAT_STORAGE,
    MASK_STAT_SOLAR,
    MASK_STAT_CHARGE,
    MASK_SYSMGR,
    MASK_MGR_USER,
    MASK_MGR_ROLE,
    MASK_MGR_PERMISSION,
    MASK_MGR_STATION,
    MASK_MGR_DEVICE,
    MASK_MGR_POLICY,
    MASK_MGR_SYSLOG,
    MASK_MGR_ALERTLOG,
};

///////////////////////////////////////////////////////////////////////////////////////////////////
/// === PvRect
class PvRect
{
public:
    PvRect();
    PvRect(int ix, int iy, int iw, int ih);

    PvRect& set(int ix, int iy, int iw, int ih);
    PvRect& setx(int ix);
    PvRect& sety(int iy);
    PvRect& setw(int iw);
    PvRect& seth(int ih);

    PvRect& shiftx(int ix);
    PvRect& shifty(int iy);
    PvRect& shiftw(int iw);
    PvRect& shifth(int ih);

public:
    int x = 0;
    int y = 0;
    int w = 100;
    int h = 30;
};

struct PvColor
{
    int r;
    int g;
    int b;
    int a;

    PvColor(int r, int g, int b, int a = 255) : r(r), g(g), b(b), a(a) {}
    std::string rgb()
    {
        return "rgb(" + std::to_string(r) + "," + std::to_string(g) + "," + std::to_string(b) + ")";
    }
    std::string rgba()
    {
        return "rgb(" + std::to_string(r) + "," + std::to_string(g) + "," + std::to_string(b) + "," + std::to_string(a) + ")";
    }
};


class PvObject
{
public:
    PARAM* p = NULL;
    int pvid = PV_ID_NUL;
    PvObject(PARAM* p) : p(p) {}
    void show(bool v) { if (p && pvid != PV_ID_NUL) { v ? pvShow(p, pvid) : pvHide(p, pvid); } }
    virtual EPvCode onEventNull(int pvid) { return EPvCode::NUL; }
    virtual EPvCode onEventButton(int pvid) { return EPvCode::NUL; }
    virtual EPvCode onEventText() { return EPvCode::NUL; }
};

class PvMask : public PvObject
{
public:
    PvMask(PARAM* p) : PvObject(p) {};

    virtual int initUI(EPvCode pvcode) { return 0; };
};

class PvUser;

class PvApp
{
public:
    static void setPvUser(PARAM* p, PvUser* pvuser);
    static PvUser* getPvUser(PARAM* p);

    static int pvid(PARAM* p);
    static void reset(PARAM* p);

    static EPvCode getPvCode(std::string name);

    static void bind(PARAM* p, PvEvent eid, int pvid, std::function<void(std::string text)> cb);
    static void dispatch(PARAM* p, PvEvent eid, int pvid, std::string text);

    static int widget(PARAM* p, int parent, int x, int y, int w, int h);

    static int label(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");

    static int labelCenter(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");

    static int labelAlignCenter(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");
    
    static int button(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");

    static int image(PARAM* p, int parent, int x, int y, int w, int h, const char* filename);

    static int combox(PARAM* p, int parent, int x, int y, int w, int h, const std::vector<std::string>& vecItems, int index=0);

    static int textedit(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");

    static int multiTextedit(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string QSS = "");

    static int radioButton(PARAM* p, int parent, int x, int y, int w, int h, std::string text);

    static int timeEdit(PARAM* p, int parent, int x, int y, int w, int h);

    static int lineLabel(PARAM* p, int parent, PvRect& rect, int w, std::string key, std::string val);

    static int lineTextedit(PARAM* p, int parent, PvRect& rect, int w, std::string key, std::string val);
};

