package models

import (
	"bwallet/pkg/setting"
	"bwallet/pkg/util"
	"encoding/json"
	"github.com/jinzhu/gorm"
)

type Coin struct {
	Model

	Id             int             `json:"primary_key, id,omitempty"`
	Name           string          `json:"name"`            //简称
	Nickname       json.RawMessage `json:"nickname"`        //全称
	Icon           string          `json:"icon"`            //币种图标
	Introduce      json.RawMessage `json:"introduce"`       //币种介绍
	Official       string          `json:"official"`        //官网
	Paper          string          `json:"paper"`           //白皮书
	Platform       string          `json:"platform"`        //平台
	Chain          string          `json:"chain"`           //主链
	Release        string          `json:"release"`         //发行时间
	AreaSearch     string          `json:"area_search"`     //区块查询
	PublishCount   float64         `json:"publish_count"`   //发行总量
	CirculateCount float64         `json:"circulate_count"` //流通总量
	Decimals       int             `json:"decimals"`        //币种精度
	Address        string          `json:"address"`         //合约地址
	Treaty         int             `json:"treaty"`          //币种类型
	PlatformId     string          `json:"platform_id"`
}

type Platform struct {
	Model

	Platform string `json:"platform"` //平台
}

func (c Coin) TableName() string {
	return setting.DatabaseSetting.Name_Sources + ".coin"
}

func (c Platform) TableName() string {
	return setting.DatabaseSetting.Name_Sources + ".coin"
}

/**
 * 通过id检查币种是否存在
 * @param id
 * @return
 */
func ExistCoinById(id int) (bool, error) {
	var coin Coin
	err := db.Select("id").Where("id = ?", id).First(&coin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return false, err
	}

	if coin.ID > 0 {
		return true, nil
	}

	return false, nil
}

/**
 * 获取符合条件的信息总数
 * @param id
 * @return
 */
func GetCoinTotal(maps interface{}) (int, error) {
	var count int
	var platform_id int
	term := make(map[string]interface{})
	for key, val := range maps.(map[string]interface{}) {
		if ("platform_id" == key) {
			platform_id = util.ToInt(val)
		} else {
			term[key] = val
		}
	}
	var err error
	if 0 == platform_id {
		err = db.Model(&Coin{}).Where(term).Count(&count).Error
	} else {
		err = db.Model(&Coin{}).Where("JSON_CONTAINS(?, platform_id)", platform_id).Where(term).Count(&count).Error
	}
	if err != nil {
		return 0, err
	}

	return count, nil
}

func GetAllPlatform(maps interface{}) ([]*Platform, error) {
	var platforms []*Platform

	err := db.Where("platform <> ''").Where(maps).Group("platform").Find(&platforms).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return platforms, nil
}

/**
 * 获取符合条件的信息
 * @param id
 * @return
 */
func GetCoins(pageNum, pageSize int, maps interface{}) ([]*Coin, error) {
	var coins []*Coin
	var platform_id int
	term := make(map[string]interface{})
	for key, val := range maps.(map[string]interface{}) {
		if ("platform_id" == key) {
			platform_id = util.ToInt(val)
		} else {
			term[key] = val
		}
	}

	var err error
	if 0 == platform_id {
		err = db.Where(term).Offset(pageNum).Limit(pageSize).Find(&coins).Error
	} else {
		err = db.Where("JSON_CONTAINS(?, platform_id)", platform_id).Where(term).Offset(pageNum).Limit(pageSize).Find(&coins).Error
	}

	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return coins, nil
}

func Find(name string, chain string) (*Coin, error) {
	var coin Coin

	err := db.Where("name = ? and chain = ?", name, chain).First(&coin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	err = db.Model(&coin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return &coin, nil
}

/**
 * 通过id获取指定币种信息
 * @param id
 * @return
 */
func GetCoin(id int) (*Coin, error) {
	var coin Coin
	err := db.Where("id = ?", id).First(&coin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	err = db.Model(&coin).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return &coin, nil
}

/**
 * 添加币种信息
 * @param
 * @return
 */
func AddCoin(data map[string]interface{}) (error) {
	coin := Coin{
		Name:           data["name"].(string),
		Nickname:       data["nickname"].(json.RawMessage),
		Icon:           data["icon"].(string),
		Introduce:      data["introduce"].(json.RawMessage),
		Official:       data["official"].(string),
		Paper:          data["paper"].(string),
		Platform:       data["platform"].(string),
		Chain:          data["chain"].(string),
		Release:        data["release"].(string),
		AreaSearch:     data["area_search"].(string),
		PublishCount:   data["publish_count"].(float64),
		CirculateCount: data["circulate_count"].(float64),
		Decimals:       data["decimals"].(int),
		Address:        data["address"].(string),
		PlatformId:     data["platform_id"].(string),
		Treaty:         data["treaty"].(int),
	}
	if err := db.Create(&coin).Error; err != nil {
		return err
	}

	return nil
}

/**
 * 更新币种信息
 * @param
 * @return
 */
func EditCoin(id int, data interface{}) error {
	if err := db.Model(&Coin{}).Where("id = ?", id).Updates(data).Error; err != nil {
		return err
	}

	return nil
}

/**
 * 删除币种信息
 * @param
 * @return
 */
func DeleteCoin(id int) error {
	if err := db.Where("id = ?", id).Delete(Coin{}).Error; err != nil {
		return err
	}

	return nil
}

func GetCoinsPlatform() ([]*Coin, error) {
	var coins []*Coin
	err := db.Select("platform").Where("platform <> ?", "").Group("platform").Find(&coins).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return coins, nil
}

func GetCoinChains() ([]*Coin, error) {
	var coins []*Coin
	err := db.Select("chain").Where("chain <> ?", "").Group("chain").Find(&coins).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return coins, nil
}
