package models

import (
	"errors"
	"fmt"
	"mtp2_if/db"
	"time"

	"gopkg.in/mgo.v2/bson"
)

// CycleType 周期类型
type CycleType int

const (
	// CycleTypeSecond 周期类型 - 秒
	CycleTypeSecond CycleType = 0
	// CycleTypeMinutes1 周期类型 - 1分钟
	CycleTypeMinutes1 CycleType = 1
	// CycleTypeMinutes5 周期类型 - 5分钟
	CycleTypeMinutes5 CycleType = 2
	// CycleTypeMinutes30 周期类型 - 30分钟
	CycleTypeMinutes30 CycleType = 3
	// CycleTypeMinutes60 周期类型 - 60分钟
	CycleTypeMinutes60 CycleType = 4
	// CycleTypeMinutes120 周期类型 - 2小时
	CycleTypeMinutes120 CycleType = 120
	// CycleTypeMinutes240 周期类型 - 4小时
	CycleTypeMinutes240 CycleType = 240
	// CycleTypeMinutesDay 周期类型 - 日线
	CycleTypeMinutesDay CycleType = 11
	// CycleTypeWeek 周期类型 - 周线
	CycleTypeWeek CycleType = 12
	// CycleTypeMonth 周期类型 - 月线
	CycleTypeMonth CycleType = 13
	// CycleTypeYear 周期类型 - 年线
	CycleTypeYear CycleType = 14
	// CycleTypeTik 周期类型 - Tik
	CycleTypeTik CycleType = 10
)

// CycleData MongoDB中历史数据模型
type CycleData struct {
	ID    bson.ObjectId `json:"-" bson:"_id"` // id
	GC    string        `bson:"GC"`           // 商品代码
	ST    int           `json:"-" bson:"ST"`  // 时间戳
	SST   string        `bson:"SST"`          // 时间文本
	Open  int           `bson:"Open"`         // 开盘价
	High  int           `bson:"High"`         // 最高价
	Low   int           `bson:"Low"`          // 最低价
	Close int           `bson:"Close"`        // 收盘价
	TV    int           `bson:"TV"`           // 总量
	TT    int           `bson:"TT"`           // 总金额
	HV    int           `bson:"HV"`           // 持仓量
	SP    int           `bson:"SP"`           // 结算价，日线周期（包括）以上才有
	FI    bool          `json:"FI"`           // 是否补充数据
}

// TikData MongoDB中Tik数据模型
type TikData struct {
	ID  bson.ObjectId `json:"-" bson:"_id"` // id
	GC  string        `bson:"GC"`           // 商品代码
	TD  int           `bson:"TD"`           // 交易日时间戳
	AT  int           `bson:"AT"`           // 行情时间戳
	SAT string        `bson:"SAT"`          // 行情时间文本
	PE  int           `bson:"PE"`           // 现价
	Vol int           `bson:"Vol"`          // 现量
	TT  int           `bson:"TT"`           // 现金额
	Bid int           `bson:"Bid"`          // 买价
	BV  int           `bson:"BV"`           // 买量
	Ask int           `bson:"Ask"`          // 卖价
	AV  int           `bson:"AV"`           // 卖量
	HV  int           `bson:"HV"`           // 持仓量
	HI  int           `bson:"HI"`           // 单笔持仓
	TDR int           `bson:"TDR"`          // 交易方向
	TK  int           `bson:"TK"`           // 交易类型
	OId int           `bson:"OId"`          // 行情序号
}

// Quoteday 行情盘面
type Quoteday struct {
	Id                   int64  `xorm:"pk autoincr BIGINT(20)"`
	Exchangedate         int64  `xorm:"not null BIGINT(20)"`           // 交易日
	Goodscode            string `xorm:"not null unique CHAR(10)"`      // 商品代码
	Exchangecode         int    `xorm:"INT(11)"`                       // 交易所代码
	Preclose             int64  `xorm:"default 0 BIGINT(20)"`          // 昨收
	Opentime             int64  `xorm:"BIGINT(20)"`                    // 开盘时间
	Opened               int64  `xorm:"not null default 0 BIGINT(20)"` // 开盘价
	Highest              int64  `xorm:"not null default 0 BIGINT(20)"` // 最高价
	Lowest               int64  `xorm:"not null default 0 BIGINT(20)"` // 最低价
	Lasttime             string `xorm:"VARCHAR(20)"`                   // 行情时间（只有现价变化行情时间才变化）
	Utclasttime          int64  `xorm:"not null BIGINT(20)"`           // utc的行情时间
	Last                 int64  `xorm:"not null BIGINT(20)"`           // 最新价
	Lastvolume           int64  `xorm:"default 0 BIGINT(20)"`          // 最新成交量
	Lastturnover         int64  `xorm:"default 0 BIGINT(20)"`          // 最新成交金额
	Totalbidvolume       int64  `xorm:"default 0 BIGINT(20)"`          // 外盘
	Totalaskvolume       int64  `xorm:"default 0 BIGINT(20)"`          // 内盘
	Totalvolume          int64  `xorm:"default 0 BIGINT(20)"`          // 总量
	Totalturnover        int64  `xorm:"default 0 BIGINT(20)"`          // 总金额
	Bid                  int64  `xorm:"default 0 BIGINT(20)"`          // 买1
	Bid2                 int64  `xorm:"default 0 BIGINT(20)"`          // 买2
	Bid3                 int64  `xorm:"default 0 BIGINT(20)"`          // 买3
	Bid4                 int64  `xorm:"default 0 BIGINT(20)"`          // 买4
	Bid5                 int64  `xorm:"default 0 BIGINT(20)"`          // 买5
	Bidvolume            int64  `xorm:"default 0 BIGINT(20)"`          // 买量1
	Bidvolume2           int64  `xorm:"default 0 BIGINT(20)"`          // 买量2
	Bidvolume3           int64  `xorm:"default 0 BIGINT(20)"`          // 买量3
	Bidvolume4           int64  `xorm:"default 0 BIGINT(20)"`          // 买量4
	Bidvolume5           int64  `xorm:"default 0 BIGINT(20)"`          // 买量5
	Ask                  int64  `xorm:"default 0 BIGINT(20)"`          // 卖1
	Ask2                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖2
	Ask3                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖3
	Ask4                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖4
	Ask5                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖5
	Askvolume            int64  `xorm:"default 0 BIGINT(20)"`          // 卖量1
	Askvolume2           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量2
	Askvolume3           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量3
	Askvolume4           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量4
	Askvolume5           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量5
	Presettle            int64  `xorm:"default 0 BIGINT(20)"`          // 昨结价
	Settle               int64  `xorm:"default 0 BIGINT(20)"`          // 结算价
	Preholdvolume        int64  `xorm:"default 0 BIGINT(20)"`          // 昨持仓
	Holdvolume           int64  `xorm:"default 0 BIGINT(20)"`          // 持仓
	Averageprice         int64  `xorm:"default 0 BIGINT(20)"`          // 均价
	Orderid              int64  `xorm:"default 0 BIGINT(20)"`          // 序号
	Limitup              int64  `xorm:"default 0 BIGINT(20)"`          // 涨停价
	Limitdown            int64  `xorm:"default 0 BIGINT(20)"`          // 跌停价
	Inventory            int64  `xorm:"default 0 BIGINT(20)"`          // 库存
	Holdincrement        int64  `xorm:"default 0 BIGINT(20)"`          // 单笔持仓
	Iscleared            int    `xorm:"INT(11)"`                       // 是否清盘标志
	Issettled            int    `xorm:"INT(11)"`                       // 是否结算标志
	Bidqueueinfo         string `xorm:"VARCHAR(2000)"`                 // 大利市买港股用
	Askqueueinfo         string `xorm:"VARCHAR(2000)"`                 // 大利市卖港股用
	Bidorderid           int64  `xorm:"BIGINT(20)"`                    // 买单号1
	Bidorderid2          int64  `xorm:"BIGINT(20)"`                    // 买单号2
	Bidorderid3          int64  `xorm:"BIGINT(20)"`                    // 买单号3
	Bidorderid4          int64  `xorm:"BIGINT(20)"`                    // 买单号4
	Bidorderid5          int64  `xorm:"BIGINT(20)"`                    // 买单号5
	Askorderid           int64  `xorm:"BIGINT(20)"`                    // 卖单号1
	Askorderid2          int64  `xorm:"BIGINT(20)"`                    // 卖单号2
	Askorderid3          int64  `xorm:"BIGINT(20)"`                    // 卖单号3
	Askorderid4          int64  `xorm:"BIGINT(20)"`                    // 卖单号4
	Askorderid5          int64  `xorm:"BIGINT(20)"`                    // 卖单号5
	Lastlot              int64  `xorm:"BIGINT(20)"`                    // 最新成交手数
	Totallot             int64  `xorm:"BIGINT(20)"`                    // 总手数
	Strikeprice          int64  `xorm:"BIGINT(20)"`                    // 发行价
	Cleartime            int64  `xorm:"BIGINT(20)"`                    // 清盘时间
	Calloptionpremiums   int64  `xorm:"default 0 BIGINT(20)"`          // 认购期权1
	Calloptionpremiums2  int64  `xorm:"default 0 BIGINT(20)"`          // 认购期权2
	Calloptionpremiums3  int64  `xorm:"default 0 BIGINT(20)"`          // 认购期权3
	Calloptionpremiums4  int64  `xorm:"default 0 BIGINT(20)"`          // 认购期权4
	Calloptionpremiums5  int64  `xorm:"default 0 BIGINT(20)"`          // 认购期权5
	Putoptionpremiums    int64  `xorm:"default 0 BIGINT(20)"`          // 认沽期权1
	Putoptionpremiums2   int64  `xorm:"default 0 BIGINT(20)"`          // 认沽期权2
	Putoptionpremiums3   int64  `xorm:"default 0 BIGINT(20)"`          // 认沽期权3
	Putoptionpremiums4   int64  `xorm:"default 0 BIGINT(20)"`          // 认沽期权4
	Putoptionpremiums5   int64  `xorm:"default 0 BIGINT(20)"`          // 认沽期权5
	Nontotalvolume       int64  `xorm:"default 0 BIGINT(20)"`          // 非交易总量
	Nontotalholdervolume int64  `xorm:"default 0 BIGINT(20)"`          // 非交易持仓量
	Nontotalturnover     int64  `xorm:"default 0 BIGINT(20)"`          // 非交易总金额
	Nontotallot          int64  `xorm:"default 0 BIGINT(20)"`          // 非交易总手数
	Publictradetype      string `xorm:"VARCHAR(2)"`                    // 公共交易标志类型 港股专用
	Iep                  int64  `xorm:"default 0 BIGINT(20)"`          // 平衡价 港股专用
	Iev                  int64  `xorm:"default 0 BIGINT(20)"`          // 平衡量 港股专用
	Grepmarketprice      int64  `xorm:"default 0 BIGINT(20)"`          // 暗盘价 港股专用
	Bid6                 int64  `xorm:"default 0 BIGINT(20)"`          // 买6
	Bid7                 int64  `xorm:"default 0 BIGINT(20)"`          // 买7
	Bid8                 int64  `xorm:"default 0 BIGINT(20)"`          // 买8
	Bid9                 int64  `xorm:"default 0 BIGINT(20)"`          // 买9
	Bid10                int64  `xorm:"default 0 BIGINT(20)"`          // 买10
	Bidvolume6           int64  `xorm:"default 0 BIGINT(20)"`          // 买量6
	Bidvolume7           int64  `xorm:"default 0 BIGINT(20)"`          // 买量7
	Bidvolume8           int64  `xorm:"default 0 BIGINT(20)"`          // 买量8
	Bidvolume9           int64  `xorm:"default 0 BIGINT(20)"`          // 买量9
	Bidvolume10          int64  `xorm:"default 0 BIGINT(20)"`          // 买量10
	Ask6                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖6
	Ask7                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖7
	Ask8                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖8
	Ask9                 int64  `xorm:"default 0 BIGINT(20)"`          // 卖9
	Ask10                int64  `xorm:"default 0 BIGINT(20)"`          // 卖10
	Askvolume6           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量6
	Askvolume7           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量7
	Askvolume8           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量8
	Askvolume9           int64  `xorm:"default 0 BIGINT(20)"`          // 卖量9
	Askvolume10          int64  `xorm:"default 0 BIGINT(20)"`          // 卖量10
	Bidordervolume       int64  `xorm:"default 0 BIGINT(20)"`          // 买单量1
	Bidordervolume2      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量2
	Bidordervolume3      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量3
	Bidordervolume4      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量4
	Bidordervolume5      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量5
	Bidordervolume6      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量6
	Bidordervolume7      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量7
	Bidordervolume8      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量8
	Bidordervolume9      int64  `xorm:"default 0 BIGINT(20)"`          // 买单量9
	Bidordervolume10     int64  `xorm:"default 0 BIGINT(20)"`          // 买单量10
	Askordervolume       int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量1
	Askordervolume2      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量2
	Askordervolume3      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量3
	Askordervolume4      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量4
	Askordervolume5      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量5
	Askordervolume6      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量6
	Askordervolume7      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量7
	Askordervolume8      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量8
	Askordervolume9      int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量9
	Askordervolume10     int64  `xorm:"default 0 BIGINT(20)"`          // 卖单量10
}

// TableName is Quoteday
func (*Quoteday) TableName() string {
	return "quoteday"
}

// GetHistoryCycleDatas 获取历史数据
// 参数 cycleType CycleType 周期类型
// 参数 goodsCode string 商品代码
// 参数 startTime time.Time 开始时间（闭区间）
// 参数 endTime time.Time 结束时间（闭区间）
// 参数 count int 条数
// 参数 isAscForST bool 是否按时间顺序排序，默认为时间倒序排序
// 返回值 []CycleData 历史数据
// 返回值 error 错误
func GetHistoryCycleDatas(cycleType CycleType, goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]CycleData, error) {
	db := db.GetMongoDB()

	// 获取目标Collection
	collection := "mincycle"
	switch cycleType {
	case CycleTypeTik:
		collection = "quotetik"
	case CycleTypeMinutes1:
		collection = "mincycle"
	case CycleTypeMinutes5:
		collection = "min5cycle"
	case CycleTypeMinutes30:
		collection = "min30cycle"
	case CycleTypeMinutes60:
		collection = "min60cycle"
	case CycleTypeMinutes240:
		collection = "min240cycle"
	case CycleTypeMinutesDay:
		collection = "daycycle"
	case CycleTypeWeek:
		collection = "weekcycle"
	case CycleTypeMonth:
		collection = "monthcycle"
	case CycleTypeYear:
		collection = "yearcycle"
	default:
		return nil, errors.New("不支持的周期类型")
	}
	c := db.C(collection)

	// 按时间排序
	sort := "-ST"
	if isAscForST {
		sort = "ST"
	}

	// 查询数据
	var cycleDatas []CycleData
	m := bson.M{"GC": goodsCode}
	if startTime != nil && endTime == nil {
		m["ST"] = bson.M{"$gte": startTime.Unix()}
	} else if startTime == nil && endTime != nil {
		m["ST"] = bson.M{"$lte": endTime.Unix()}
	} else if startTime != nil && endTime != nil {
		m["ST"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()}
	}
	query := c.Find(m)
	if count > 0 {
		query = query.Limit(count)
	}
	if err := query.Sort(sort).All(&cycleDatas); err != nil {
		return nil, err
	}

	return cycleDatas, nil
}

// GetHistoryTikDatas 获取历史数据
// 参数 goodsCode string 商品代码
// 参数 startTime time.Time 开始时间（闭区间）
// 参数 endTime time.Time 结束时间（闭区间）
// 参数 count int 条数
// 参数 isAscForST bool 是否按时间顺序排序，默认为时间倒序排序
// 返回值 []TikData Tik数据
// 返回值 error 错误
func GetHistoryTikDatas(goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]TikData, error) {
	db := db.GetMongoDB()

	// 获取目标Collection
	collection := "quotetik"
	c := db.C(collection)

	// 按时间排序
	sort := "-AT"
	if isAscForST {
		sort = "AT"
	}

	// 查询数据
	var tikDatas []TikData
	m := bson.M{"GC": goodsCode}
	if startTime != nil && endTime == nil {
		m["AT"] = bson.M{"$gte": startTime.Unix()}
	} else if startTime == nil && endTime != nil {
		m["AT"] = bson.M{"$lte": endTime.Unix()}
	} else if startTime != nil && endTime != nil {
		m["AT"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()}
	}
	query := c.Find(m)
	if count > 0 {
		query = query.Limit(count)
	}
	if err := query.Sort(sort).All(&tikDatas); err != nil {
		return nil, err
	}

	return tikDatas, nil
}

// GetQuoteDays 获取目标商品的盘面数据
// 参数 goodsCodes string 商品代码字串，以“,”分隔
// 返回 []Quoteday 盘面数据
// 返回 error error
func GetQuoteDays(goodsCodes string) ([]Quoteday, error) {
	engine := db.GetMySQLEngine()

	datas := make([]Quoteday, 0)
	if err := engine.Where(fmt.Sprintf("goodscode in (%s)", goodsCodes)).Find(&datas); err != nil {
		return nil, err
	}

	return datas, nil
}
