#ifndef EMBDATA_H
#define EMBDATA_H

#include <QList>
#include <QByteArray>
#include <QApplication>
#include <QDir>
#include <QImage>
#include <qmath.h>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QPainter>
#include <QObject>
#include <QVector>
//#include "machine/comm/datadef.h"
#include "machine/comm/crc16.h"
#include "outline.h"

#define ZERO				                1e-6
#define DIRECTION 8

#define MAX_EMB_STEP    121//四字节针步最大针步限制
#define DEFAULT_JUMP    70//默认针步大小
#define TOTAL_NEEDLE_NUM   122
//总的针杆数,
//绣花32个(1-32),
//冲孔16个(33-48),
//缝纫2个(49-50),
//盘带2个(51-52),
////预留1个(52),之前盘带是1个，后来变成了2个
//毛巾16个(53-68),
//链式16个(69-84)，
//缠绕9个（85-93)，
//预留7个(94-100),
//锯齿6个(101-106),
//预留6个(107-112),
//激光1个(113-122)

#define EMB_NEEDLE_NUM      32//绣花32个针杆
#define PUNCH_NEEDLE_NUM  16//冲孔16个针杆
#define SEW_NEEDLE_NUM      2 //缝纫2个针杆
#define RIBBON_NEEDLE_NUM      2 //盘带2个针杆
//#define REV1_NEEDLE_NUM       1//预留1个针杆
#define TOWEL_NEEDLE_NUM      16 //毛巾16个针杆
#define CHAIN_NEEDLE_NUM      16 //链式16个针杆
#define COIL_NEEDLE_NUM        9//缠绕9个针杆
#define REV2_NEEDLE_NUM       7//预留7个针杆
#define SAWTOOTH_NEEDLE_NUM       6//锯齿6个针杆
#define REV3_NEEDLE_NUM       6//预留6个针杆
#define LASER_NEEDLE_NUM			10// 激光10个针杆

#define SEQUIN_NUM      12 //亮片最大数量
#define BEAD_NUM      6 //散珠最大数量
#define COLORTABLE_NUM  512//色序表

#define EMB_PREVIEW_SIDE    (32)     // 留边大小
#define TENTHOUSANDNEEDLE   100000

#define EMB_SHOWDIRX    (-1)   // X向显示坐标和数据坐标的差异
#define EMB_SHOWDIRY    (1)    // Y向显示坐标和数据坐标的差异
#define OUTLINESTEPFACTOR  100 // 生成轮廓花样针步乘以的系数，单位是0.01，所以乘以100

#define COLOR_GREY  186 //纯灰色的rgb

#define PI10000 31416
#define PI20000 62832

// 花样轮廓
typedef struct
{
    int x;
    int y;
    int dir;
    char var;
}__attribute__ ((packed)) OutLineItem;


class EmbData: public QObject
{
    Q_OBJECT

public:
    EmbData();
    ~EmbData();

public:
    void clear();
    void initColor(int cnum = 0, QRgb * pColor = NULL);//初始化颜色
    QByteArray & getDsDat();//得到转换后的ds16数据
    bool checkFirstEndNeedle();//检查起针和末针的x坐标是否一致，如果相差0.5mm以上绗绣机是不能绣作的，需要重新打版
    inline DataDs16FileHead * getDsDatHead(){return m_pEmbDs16Head;}//得到转换后的ds16数据的文件头

    void setDsDatHeadFileID(u32 fileid);//设置数据区文件头的fileid
    void getAbsDatRangeXY();//得到绝对坐标的maxXY和minXY

    void appendACombEmbFile(QString filePath);//附加一个绝对坐标的绣花文件(组合文件)
    void appendAEmbAbsFile(QString filePath,QByteArray array,int mirror = 0);//附加一个绝对坐标的花样文件

    int addLockStitchs(int locktimes, int locksteps, int lockstepsize, int jumpStichs,int isColorlock);
    int mergeMinStep(u16 minStep, int mergeStep);    //合并小针步

    int removeAEmbFile(int idx = -1);//删除一个绣花文件
    int saveAsCombFile(QString fullpathname,QString name);//保存为comb文件(组合文件的格式)

public:
    int getPattenNum();//得到花版个数
    inline QString getFileName(){return m_pEmbDs16Head->fileName;}//得到花版名称
    inline int getStitchNums(){return m_pEmbDs16Head->itemNums;}//得到数据的针数
    inline int getColorNums(){return m_pEmbDs16Head->colorNum;}//得到数据的色数
    inline int getTowelHighNums(){return m_pEmbDs16Head->towelHighNum;}//得到毛巾高度数
    inline int getDatWidth(){return m_pEmbDs16Head->maxX - m_pEmbDs16Head->minX;}//得到数据的图形宽度
    inline int getDatHeight(){return m_pEmbDs16Head->maxY - m_pEmbDs16Head->minY;}//得到数据的图形高度
    inline int getMaxX(){return m_pEmbDs16Head->maxX;}//得到数据最大X+
    inline int getMinX(){return m_pEmbDs16Head->minX;}//得到数据最小X-
    inline int getMaxY(){return m_pEmbDs16Head->maxY;}//得到数据最大Y+
    inline int getMinY(){return m_pEmbDs16Head->minY;}//得到数据最小Y-
    inline int getJumpNeedleNum(){return m_pEmbDs16Head->jumpNeedleNum;}//得到总的跳针数
    inline void setDsDataStepUnit(u16 unit){m_dsDataStepUnit = unit;}

public:
    void setAbsDat(QByteArray & dat);
    QByteArray &  getAbsDat(void);

    QByteArray getColorTable();//得到数据的色序表
    int getAFileDs16Range(int idx, int & beg, int & end); //得到普通花
    int getPosInfoFromNeedleIdx(int stitchIdx, int & posx, int & posy, int & posr, int & colorIdx);
    int getPosInfoFromColorIdx(int & stitchIdx, int & posx, int & posy, int & posr, int colorIdx);
    int getNeedleIdxFromColorIdx(int & needleIdx, int colorIdx, u8 & stepCtrl);
    int getNeedleIdxFromTowelHighIdx(int & needleIdx, int highIdx, u8 & stepCtrl);
    void setDs16ColorOfTable(u8* table);  //改变色序颜色
    void setNeedleColorTable(int colorIdx, int colorvalue);  //针杆颜色
    void setBeadColorTable(int colorIdx, int colorvalue);  //散珠颜色
    void setSequinColorTable(int colorIdx, int colorvalue);  //亮片颜色
    PatternParaStruct getPatternParaStruct(QString path);
    void setPatternParaStruct(PatternParaStruct paraStruct);
    void setStartPosition(int x, int y, int st = 0,u8 workHead = 1);//设置起始点

public:
    void setConvertSkipStepSize(u16 stepSize , u16 jumpStepSize );//需要插入跳针的针步大小
	void setDataStepUnit(u16 stepUnit);
    int modifyStepAngle(u16 mode = 0);//修改针步角度
    void setMcRepeatEmb(DataFileHead fileHead);//设置主控反复绣，改变ds16文件头
    int  getDataListRange(QList <QByteArray> *datList,
                       double &minX,double &maxX,double &minY,double &maxY);// 得到所有列表内花样范围
    void PaintedGrid(QVector<QVector<char> >& visited,int x,int y,int r);   // 涂格子
    void PaintedLine(QVector<QVector<char> >& visited, int begx, int begy, int endx, int endy,int zoom,int vectorH,int vectorV);// 绘制直线
    OutLineItem FindNextPos(QVector<QVector<char> >& visited,OutLineItem pos);      // 寻找下一个点
    int setNeedleXYCompensation(double valueX,double valueY);//分别设置xy针步补偿
    void setOffsetXYData(s32 EnFlag,s32 offsetX,s32 offsetY);
    double getAngle(double x1, double y1, double x2, double y2);
    int setDatSizeChange(int dsx, int dsy, int idx = -1);//设置尺寸变化
    int setMirror(int mirror, int idx = -1);//设置镜像
    int setFLip(int mirror, int idx = -1);//设置镜像
    int setRotate(int dr, int idx = -1);//设置旋转
    int setToMiddle(int idx = -1);//设置居中
    int setDatMove(int dx, int dy, int idx = -1);//设置数据移动
    void createSameColorEmbDs16Dat(int num);//按色通常并转换为ds16数据
    void createPatternOutlineFile(int outlineStep,int outlineZoom,int outlineShape = 0);//生成花样轮廓文件
    QString createBorderEmbData(QString filePath);//生成边框刺绣的数据
    QByteArray createOpenLineEmbData(QList<OpenLineNode> &list);//生成开位线绣的数据

private:
    void splitBorderStitchAndAdd(QByteArray & dat,int bx,int by,int ex,int ey);//分割针步并添加

    //此函数转换传入的绝对坐标值，是否取镜像及反复时数据之间的间距
    void convertAbsDat(QByteArray & dat,int mirror = 0);

    QList<QByteArray> getDataList(QString name);
    int createEmbDs16FromAbs();//生成DS16数据
    int reCalcDataChecksum();//重新计算文件CRC   
    QByteArray intTo2ByteArray(s16 value);//短整型转换为byte
    void drawNeedleIdxPen(int x, int y, QPainter &painter);//绘制针数索引的跟踪笔
    void eraseNeedleIdxPen(QPainter &painter);//擦除针数索引的跟踪笔
    void drawBeadOrSequin(QPainter &painter,u8 action, int bx, int by,int ex,int ey,QRgb beadColor,s16 grey = 0);//绘制散珠或亮片

public:
    int m_editedflag;//数据被编辑的标志
    int m_spaceX;//横向间隙
    int m_spaceY;//纵向移动距离

//用于调节颜色
#if(1)
    QString m_selfilename;
#endif

    double m_minX;
    double m_maxX;
    double m_minY;
    double m_maxY;

    int m_beginX;
    int m_beginY;
    int m_beginR;
	
    s32 m_enFlag;
    s32 m_offsetX;
    s32 m_offsetY;

    s16 m_sequinColorTable[SEQUIN_NUM];//亮片颜色table
    s16 m_beadColorTable[BEAD_NUM];//散珠颜色table
    s16 m_towelColorTable[TOWEL_NEEDLE_NUM];//毛巾颜色table

    s16 m_needleColorTable[TOTAL_NEEDLE_NUM];//32个绣花针杆颜色索引(后期还会增加冲孔缝纫毛巾等)
    PatternParaStruct m_patternParaStruct;//花样参数结构体
    QByteArray m_colortab;//发给下位机的数据（需要转换）

private:
    QByteArray m_embAbsData;    // 转换后的绝对坐标数据
    QList <QByteArray> m_dataAbsList;//文件绝对位置列表
    QByteArray m_embDs16Data;//发给下位机的ds16数据（需要转换）
    QList <int> m_embDatEndList;
    QList <QByteArray> m_arrayAbsList;//排列前的文件绝对位置列表
    int m_totalJumpNeedle;//总跳针数
    DataDs16FileHead * m_pEmbDs16Head;//ds16    文件头     //数据转换用的都是DataDs16FileHead
    double m_factor;//绘制数据与实际数据的缩放率
    QByteArray m_extractContours;//花样轮廓数据
    u16 m_convertSkipStepSize;
    u16 m_jumpStepSize;
    u16 m_dsDataStepUnit;   //0.01mm或0.1mm（教学一体机为步进电机，针步精度为0.1mm，需要将数据除以10）

//图形预览、刷新
public:
    //显示所有线迹（原色显示）
    //显示所有线迹（有效区域内的显示原色，其余显示灰色）
    //显示所有线迹（执行过的显示原色，其余显示灰色）
    //刷新部分线迹（缝纫中进度显示）
    enum DISP_MODE {DISP_ALL_NORMAL = 0, DISP_ALL_AREA, DISP_ALL_EXEC, DISP_EXECING};
    enum DRAW_MODE {DRAW_VIEW = 0, DRAW_PREVIEW};//绘制模式(非预览模式、预览模式)

public:
    int setViewInfo(int width, int height);//设置视图尺寸(透明背景)
    void setViewInfo(QPixmap pix);//设置视图(带背景图片背景)

    //重新重置ds16数据(换色点击取消后数据会变为单个图元的原数据，
    //若图形经过变换数据会不对，换色界面保存了最后的数据和XY范围，
    //若点击换色并取消后恢复为换色界面最后保存的数据即可)
    void reSetEmbData(QByteArray ary);
    void reSetEmbDataRange(int maxX,int minX,int maxY,int minY);

    void setEmbData(int redraw = 0);//重置数据
                                                            //是否重绘      //是否为渐变
    void setDispMode(DISP_MODE dispmode = DISP_ALL_NORMAL, int redraw = 0,int gradientFlag = 0);//设置预览模式
    void setDrawMode(DRAW_MODE drawmode = DRAW_VIEW);//设置绘制模式

    void setGreyAreaRange(int begin, int end);//设置灰色区域显示
    void setDispAreaRange(int begin, int end, int redraw = 0);//设置区域显示参数
    void setExecIndex(int index);//设置进度显示数据
    void reDraw();//重新绘图

public:
    inline QPixmap getPreviewImage(){return m_canvas;}//返回预览图片

private:
    int createDispFromEmbDs16Dat(QByteArray & ds16dat);//创建显示用的数据（为了快速显示）
    int drawImageByDispFile(int gradientFlag = 0);//用显示数据画图(是否渐变显示)
    QColor getBrightAdd(QColor embcolor);//补光增加
    QColor getBrightDec(QColor embcolor);//补光减少

private:
    void getCurvePointFillLine(QList<DsAbsItem> &inList, double indRunLen,QList<DsAbsItem> &outList);
    int getTotalDistanceFillLine(QList<DsAbsItem> *pPointList, double &dTotal);
    bool getPointInSectFillLine(const DsAbsItem &p1, const DsAbsItem &p2, const double &d, DsAbsItem &outp);
    //距p1点距离为d的点
    // d > s : out_p在p2延长线上
    // s >= d >= 0 : out_p在p1、p2线段上
    // d < 0 : out_p在p1延长线上
    bool getPointAtSect(const DsAbsItem &p1, const DsAbsItem &p2, const double &d, DsAbsItem &outp);

private:
    int m_penX, m_penY;//执行过程中绘制跟踪笔的坐标索引

    QPixmap m_canvas;
    QPixmap m_penPix;//跟踪笔绘制的临时区域

    int m_viewWidth;
    int m_viewHight;

    int m_tabelColorNum;//颜色数
    QRgb * m_pColor;//颜色rgb
    QString m_filePath;//文件路径

private:
    QByteArray m_dispDat;//绘制图形的绝对数据(进行缩放的)
    QByteArray m_ds16ToAbsDat;//ds16转换的绝对数据(用于轮廓提取)
    int m_stitchIndex;
    int m_dispIndex;
    int m_showColorBeg;
    int m_showColorEnd;
    int m_greyColorBeg;
    int m_greyColorEnd;
    DISP_MODE m_dispMode;
    DRAW_MODE m_drawMode;

signals:
    void siDrawNeedleIdx(int idx);

};

#endif // EMBDATA_H
