package controllers

import (
	"exhibitionCentre/base"
	"exhibitionCentre/config"
	"exhibitionCentre/logging"
	"exhibitionCentre/models"
	"exhibitionCentre/utils"
	"text/template"
	"time"
)

// 获取总览列表消息
type ExhibitionsRequest struct {
	Type int `mapper:"type" json:"type"` // 展览分类，对应models.Exhibition.Classification
}
type ExhibitionsResponse struct {
	Type      int                       `json:"type"`       // 展品分类
	All       []models.ExhibitionDetail `json:"all"`        // 当前类型下全部展览
	FineWorks []models.ExhibitionDetail `json:"fine_works"` // 当前类型下的精品展览
	Masters   []models.ExhibitionDetail `json:"masters"`    // 当前类型下的名家展览
}

// 查看更多消息
type MoreExhibitionsRequest struct {
	Type        int `mapper:"type" json:"type"`                 // 展览分类 | 0全部 1戏剧家 2电影电视家 3音乐家 4美术家 5曲艺家 6舞蹈家 7民间艺术家 8摄影家 9书法家 10文艺评论家 11文艺志愿者 12企业（行业）文联
	Filter      int `mapper:"filter" json:"filter"`             // 展览精选、名家等过滤 | 0全部 1精品 2名家
	StateFilter int `mapper:"state_filter" json:"state_filter"` // 展览时效状态过滤 | 0全部 1正在展览 2往期展览 3即将展览
	Page        int `mapper:"page" json:"page"`                 // 第几页
	PageSize    int `mapper:"page_size" json:"page_size"`       // 每页展览数量
}
type MoreExhibitionsResponse struct {
	Type        int                       `json:"type"`
	Filter      int                       `json:"filter"`
	StateFilter int                       `json:"state_filter"`
	Page        int                       `json:"page"`
	PageSize    int                       `json:"page_size"`
	Exhibitions []models.ExhibitionDetail `json:"exhibitions"` // 当前类型下全部展览
}

// 展览详情消息
type ExhibitionDetailRequest struct {
	ID          int `mapper:"id" json:"id"`
	Number      int `mapper:"number" json:"number"`
	IgnoreVisit int `mapper:"ignore_visit" json:"ignore_visit"`
}
type ExhibitionDetailResponse struct {
	ID        int                   `json:"id"`    // 展览id
	Style     int                   `json:"style"` // 1为现代，2为古代
	Title     string                `json:"title"`
	Subtitle  string                `json:"subtitle"`
	Cover     string                `json:"cover"`      // 封面图
	StartTime time.Time             `json:"start_time"` // 展览开始时间
	EndTime   time.Time             `json:"end_time"`   // 展览结束时间
	Likes     int                   `json:"likes"`      // 点赞数
	Flowers   int                   `json:"flowers"`    // 送花数
	Applauses int                   `json:"applauses"`  // 鼓掌数
	Rooms     []*ExhibitionRoomInfo `json:"rooms"`      // 所有开放的场馆
}

type ExhibitionRoomInfo struct {
	Number   int           `json:"number"`
	Exhibits []ExhibitInfo `json:"exhibits"`
}

type ExhibitInfo struct {
	ID       int     `json:"id"`        // 展品id
	Number   int     `json:"number"`    // 展位编号
	Width    float32 `json:"width"`     // 展品宽度(单位：米)
	Height   float32 `json:"height"`    // 展品高度(单位：米)
	OffsetX  float32 `json:"offset_x"`  // 展品横向偏移(单位：米)
	OffsetY  float32 `json:"offset_y"`  // 展品纵向偏移(单位：米)
	Url      string  `json:"url"`       // 展品图片、视频下载地址
	Title    string  `json:"title"`     // 展品标题
	StayTime int     `json:"stay_time"` // 驻足停留时间，默认值为3s
}

// 点赞消息
type ExhibitionLikeRequest struct {
	ID int `mapper:"id" json:"id"`
}
type ExhibitionLikeResponse struct {
	Count int `json:"count"`
}

// 送花消息
type ExhibitionSendFlowerRequest struct {
	ID int `mapper:"id" json:"id"`
}
type ExhibitionSendFlowerResponse struct {
	Count int `json:"count"`
}

// 鼓掌消息
type ExhibitionGiveApplauseRequest struct {
	ID int `mapper:"id" json:"id"`
}
type ExhibitionGiveApplauseResponse struct {
	Count int `json:"count"`
}

// 请求进入展览消息
type GotoExhibitionRequest struct {
	ID    int `mapper:"id" json:"id"`
	Enter int `mapper:"enter" json:"enter"`
}

// 请求进入展览
func GotoExhibition(router *base.Router) (int, []byte) {
	// 解析request数据
	var request GotoExhibitionRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Errorf("解析数据失败, err: %v\n", err.Error())
		return 400, utils.SerializeErrorData("进入展览失败!")
	}
	// 数据库获取展览
	exhibition, err := models.GetExhibition(request.ID)
	if err != nil {
		logging.Log.Errorf("数据库获取展览失败: %v\n", err.Error())
		return 400, utils.SerializeErrorData("进入展览失败!")
	}
	firstPage := "./resources/exhibition_hall/index.html"
	if request.Enter <= 0 {
		if exhibition.OpeningCeremonyUsed {
			firstPage = "./resources/opening_ceremony/index.html"
		} else if exhibition.ExhibitionHallUsed {
			firstPage = "./resources/exhibition_hall/index.html"
		} else if exhibition.StudioUsed {
			if exhibition.Style == 1 {
				firstPage = "./resources/studio_modern/index.html"
			} else if exhibition.Style == 2 {
				firstPage = "./resources/studio_ancient/index.html"
			}
		}
	} else {
		if exhibition.ExhibitionHallUsed {
			firstPage = "./resources/exhibition_hall/index.html"
		} else if exhibition.StudioUsed {
			if exhibition.Style == 1 {
				firstPage = "./resources/studio_modern/index.html"
			} else if exhibition.Style == 2 {
				firstPage = "./resources/studio_ancient/index.html"
			}
		}
	}

	page, err := template.ParseFiles(firstPage)
	if err != nil {
		logging.Log.Error("加载场景页面失败: ", err.Error())
		return 404, utils.SerializeErrorData("进入展览失败!")
	}
	page.Execute(router.Writer, nil)
	return 200, nil
}

// 获取展览详细信息
func ExhibitionDetail(router *base.Router) (int, []byte) {
	// 解析request数据
	var info ExhibitionDetailRequest
	if err := utils.ParseQuery(router.Req, &info); err != nil {
		logging.Log.Error("解析数据失败: ", err.Error())
		return 400, utils.SerializeErrorData("参数错误!")
	}
	var resp ExhibitionDetailResponse
	// 测试
	if info.Number > 0 {
		exhibitInfos := []ExhibitInfo{}
		// 获取展览
		exhibition, err := models.GetExhibition(info.ID)
		if err != nil {
			logging.Log.Error("数据库获取展览失败: ", err.Error())
			return 403, utils.SerializeErrorData("获取展览详情失败!")
		}
		// 获取展览内所有展品
		exhibits, _ := models.GetExhibitsByExhibitionId(int(exhibition.ID))
		for _, exhibit := range exhibits {
			if exhibit.RoomIndex == info.Number {
				exhibitInfos = append(exhibitInfos, ExhibitInfo{
					ID:       int(exhibit.ID),
					Number:   exhibit.Number,
					Width:    exhibit.Width,
					Height:   exhibit.Height,
					OffsetX:  exhibit.OffsetX,
					OffsetY:  exhibit.OffsetY,
					Url:      exhibit.Url,
					Title:    exhibit.Title,
					StayTime: exhibit.StayTime,
				})
			}
		}
		room := ExhibitionRoomInfo{
			Number:   info.Number,
			Exhibits: exhibitInfos,
		}
		resp = ExhibitionDetailResponse{
			ID:        int(exhibition.ID),
			Style:     exhibition.Style,
			Title:     exhibition.Title,
			Subtitle:  exhibition.Subtitle,
			Cover:     exhibition.Cover,
			StartTime: exhibition.StartTime,
			EndTime:   exhibition.EndTime,
			Likes:     exhibition.Likes,
			Flowers:   exhibition.Flowers,
			Applauses: exhibition.Applauses,
			Rooms: []*ExhibitionRoomInfo{
				&room,
			},
		}
	} else {
		// 获取展览
		exhibition, err := models.GetExhibition(info.ID)
		if err != nil {
			logging.Log.Error("数据库获取展览失败: ", err.Error())
			return 403, utils.SerializeErrorData("获取展览详情失败!")
		}
		// 获取展览内所有展品
		exhibits, _ := models.GetExhibitsByExhibitionId(int(exhibition.ID))

		// 场馆信息
		rooms := []*ExhibitionRoomInfo{}

		// 填充场馆
		if len(exhibits) > 0 {
			for _, exhibit := range exhibits {
				if !exhibition.OpeningCeremonyUsed && exhibit.RoomIndex == 1 {
					continue
				}
				if !exhibition.ExhibitionHallUsed && exhibit.RoomIndex == 2 {
					continue
				}
				if !exhibition.StudioUsed && exhibit.RoomIndex == 3 {
					continue
				}
				var room *ExhibitionRoomInfo
				for _, r := range rooms {
					if r.Number == exhibit.RoomIndex {
						room = r
						break
					}
				}
				if room == nil {
					rooms = append(rooms, &ExhibitionRoomInfo{
						Number: exhibit.RoomIndex,
						Exhibits: []ExhibitInfo{
							{
								ID:       int(exhibit.ID),
								Number:   exhibit.Number,
								Width:    exhibit.Width,
								Height:   exhibit.Height,
								OffsetX:  exhibit.OffsetX,
								OffsetY:  exhibit.OffsetY,
								Url:      exhibit.Url,
								Title:    exhibit.Title,
								StayTime: exhibit.StayTime,
							},
						},
					})
				} else {
					room.Exhibits = append(room.Exhibits, ExhibitInfo{
						ID:       int(exhibit.ID),
						Number:   exhibit.Number,
						Width:    exhibit.Width,
						Height:   exhibit.Height,
						OffsetX:  exhibit.OffsetX,
						OffsetY:  exhibit.OffsetY,
						Url:      exhibit.Url,
						Title:    exhibit.Title,
						StayTime: exhibit.StayTime,
					})
				}
			}
		}
		resp = ExhibitionDetailResponse{
			ID:        int(exhibition.ID),
			Style:     exhibition.Style,
			Title:     exhibition.Title,
			Subtitle:  exhibition.Subtitle,
			Cover:     exhibition.Cover,
			StartTime: exhibition.StartTime,
			EndTime:   exhibition.EndTime,
			Likes:     exhibition.Likes,
			Flowers:   exhibition.Flowers,
			Applauses: exhibition.Applauses,
			Rooms:     rooms,
		}
	}
	// 访问记录
	if info.IgnoreVisit <= 0 && info.Number > 1 {
		visit, _ := models.GetTodayVisitStatistic(info.ID)
		if visit == nil {
			visit = &models.VisitStatistic{
				Count:        1,
				ExhibitionId: uint(info.ID),
			}
			models.CreateVisitStatistic(visit)
		} else {
			visit.Count += 1
			models.UpdateVisitStatistic(visit)
		}
	}
	return 200, utils.Serialize(resp)
}

/****************************** 前端接口 ******************************/
func Exhibitions(router *base.Router) (int, []byte) {
	// 解析request数据
	var request ExhibitionsRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Error("解析数据失败: ", err.Error())
		return 400, utils.SerializeErrorData("参数错误!")
	}
	exhibitions, err := models.GetExhibitionsByClassification(request.Type, 1, config.ExhibitionConfig.PreviewPageSize)
	if err != nil {
		logging.Log.Errorf("根据展览分类(%v)查询数据失败: %v\n", request.Type, err.Error())
		return 400, utils.SerializeErrorData("获取展览列表失败!")
	}
	// 精品展览
	fineWorks, err := models.GetExhibitionsByClassificationAndFineWork(request.Type, 1, config.ExhibitionConfig.PreviewPageSize)
	if err != nil {
		logging.Log.Errorf("根据展览分类(%v)查询精品展览数据失败: %v\n", request.Type, err.Error())
		return 400, utils.SerializeErrorData("获取展览列表失败!")
	}
	// 名家展览
	masters, err := models.GetExhibitionsByClassificationAndMaster(request.Type, 1, config.ExhibitionConfig.PreviewPageSize)
	if err != nil {
		logging.Log.Errorf("根据展览分类(%v)查询名家展览数据失败: %v\n", request.Type, err.Error())
		return 400, utils.SerializeErrorData("获取展览列表失败!")
	}
	// 不区分精品、名家
	exhibitionDetails := []models.ExhibitionDetail{}
	for _, d := range exhibitions {
		exhibitionDetails = append(exhibitionDetails, models.ExhibitionDetail{
			ID:                  int(d.ID),
			Style:               d.Style,
			Title:               d.Title,
			Subtitle:            d.Subtitle,
			Cover:               d.Cover,
			StartTime:           d.StartTime,
			EndTime:             d.EndTime,
			OpeningCeremonyUsed: d.OpeningCeremonyUsed,
			ExhibitionHallUsed:  d.ExhibitionHallUsed,
			StudioUsed:          d.StudioUsed,
			Likes:               d.Likes,
			Flowers:             d.Flowers,
			Applauses:           d.Applauses,
		})
	}
	// 精品展览信息
	fineWorkDetails := []models.ExhibitionDetail{}
	for _, d := range fineWorks {
		fineWorkDetails = append(fineWorkDetails, models.ExhibitionDetail{
			ID:                  int(d.ID),
			Style:               d.Style,
			Title:               d.Title,
			Subtitle:            d.Subtitle,
			Cover:               d.Cover,
			StartTime:           d.StartTime,
			EndTime:             d.EndTime,
			OpeningCeremonyUsed: d.OpeningCeremonyUsed,
			ExhibitionHallUsed:  d.ExhibitionHallUsed,
			StudioUsed:          d.StudioUsed,
			Likes:               d.Likes,
			Flowers:             d.Flowers,
			Applauses:           d.Applauses,
		})
	}
	// 名家展览信息
	masterDetails := []models.ExhibitionDetail{}
	for _, d := range masters {
		masterDetails = append(masterDetails, models.ExhibitionDetail{
			ID:                  int(d.ID),
			Style:               d.Style,
			Title:               d.Title,
			Subtitle:            d.Subtitle,
			Cover:               d.Cover,
			StartTime:           d.StartTime,
			EndTime:             d.EndTime,
			OpeningCeremonyUsed: d.OpeningCeremonyUsed,
			ExhibitionHallUsed:  d.ExhibitionHallUsed,
			StudioUsed:          d.StudioUsed,
			Likes:               d.Likes,
			Flowers:             d.Flowers,
			Applauses:           d.Applauses,
		})
	}
	resp := ExhibitionsResponse{
		Type:      request.Type,
		All:       exhibitionDetails,
		FineWorks: fineWorkDetails,
		Masters:   masterDetails,
	}
	return 200, utils.Serialize(&resp)
}

func MoreExhibitions(router *base.Router) (int, []byte) {
	// 解析request数据
	var request MoreExhibitionsRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Error("解析数据失败: ", err.Error())
		return 400, utils.SerializeErrorData("参数错误!")
	}
	pageSize := config.ExhibitionConfig.PageSize
	if request.PageSize > 0 {
		pageSize = request.PageSize
	}
	var exhibitions []models.Exhibition
	var err error
	if request.Filter == 0 { // 不区分
		// 展览时效状态判断
		if request.StateFilter == 0 { // 不区分
			exhibitions, err = models.GetExhibitionsByClassification(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 1 { // 正在展览
			exhibitions, err = models.GetNowExhibitionsByClassification(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 2 { // 过期展览
			exhibitions, err = models.GetPastExhibitionsByClassification(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 3 { // 即将展览
			exhibitions, err = models.GetFutureExhibitionsByClassification(request.Type, request.Page, pageSize)
		}
	} else if request.Filter == 1 { // 精品
		// 展览时效状态判断
		if request.StateFilter == 0 { // 不区分
			exhibitions, err = models.GetExhibitionsByClassificationAndFineWork(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 1 { // 正在展览
			exhibitions, err = models.GetNowExhibitionsByClassificationAndFineWork(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 2 { // 过期展览
			exhibitions, err = models.GetPastExhibitionsByClassificationAndFineWork(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 3 { // 即将展览
			exhibitions, err = models.GetFutureExhibitionsByClassificationAndFineWork(request.Type, request.Page, pageSize)
		}
	} else if request.Filter == 2 { // 名家
		// 展览时效状态判断
		if request.StateFilter == 0 { // 不区分
			exhibitions, err = models.GetExhibitionsByClassificationAndMaster(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 1 { // 正在展览
			exhibitions, err = models.GetNowExhibitionsByClassificationAndMaster(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 2 { // 过期展览
			exhibitions, err = models.GetPastExhibitionsByClassificationAndMaster(request.Type, request.Page, pageSize)
		} else if request.StateFilter == 3 { // 即将展览
			exhibitions, err = models.GetFutureExhibitionsByClassificationAndMaster(request.Type, request.Page, pageSize)
		}
	}
	if err != nil {
		logging.Log.Errorf("根据展览分类(%v)查询更多展览数据失败: %v\n", request.Type, err.Error())
		return 400, utils.SerializeErrorData("查询更多展览失败!")
	}
	exhibitionDetails := []models.ExhibitionDetail{}
	for _, ex := range exhibitions {
		exhibitionDetails = append(exhibitionDetails, models.ExhibitionDetail{
			ID:                  int(ex.ID),
			Style:               ex.Style,
			Title:               ex.Title,
			Subtitle:            ex.Subtitle,
			Cover:               ex.Cover,
			StartTime:           ex.StartTime,
			EndTime:             ex.EndTime,
			OpeningCeremonyUsed: ex.OpeningCeremonyUsed,
			ExhibitionHallUsed:  ex.ExhibitionHallUsed,
			StudioUsed:          ex.StudioUsed,
			Likes:               ex.Likes,
			Flowers:             ex.Flowers,
			Applauses:           ex.Applauses,
		})
	}
	resp := MoreExhibitionsResponse{
		Type:        request.Type,
		Filter:      request.Filter,
		StateFilter: request.StateFilter,
		Page:        request.Page,
		PageSize:    pageSize,
		Exhibitions: exhibitionDetails,
	}
	return 200, utils.Serialize(&resp)
}

// 点赞
func ExhibitionLike(router *base.Router) (int, []byte) {
	// 解析request数据
	var request ExhibitionLikeRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Errorf("解析数据失败, err: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览点赞失败!")
	}
	// 数据库获取展览
	exhibition, err := models.GetExhibition(request.ID)
	if err != nil {
		logging.Log.Errorf("数据库获取展览失败: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览点赞失败!")
	}
	exhibition.Likes += 1
	models.UpdateExhibition(exhibition)

	resp := ExhibitionLikeResponse{
		Count: exhibition.Likes,
	}
	return 200, utils.Serialize(&resp)
}

// 送花
func ExhibitionSendFlower(router *base.Router) (int, []byte) {
	// 解析request数据
	var request ExhibitionSendFlowerRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Errorf("解析数据失败, err: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览送花失败!")
	}
	// 数据库获取展览
	exhibition, err := models.GetExhibition(request.ID)
	if err != nil {
		logging.Log.Errorf("数据库获取展览失败: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览送花失败!")
	}
	exhibition.Flowers += 1
	models.UpdateExhibition(exhibition)

	resp := ExhibitionSendFlowerResponse{
		Count: exhibition.Flowers,
	}
	return 200, utils.Serialize(&resp)
}

// 鼓掌
func ExhibitionGiveApplause(router *base.Router) (int, []byte) {
	// 解析request数据
	var request ExhibitionGiveApplauseRequest
	if err := utils.ParseQuery(router.Req, &request); err != nil {
		logging.Log.Errorf("解析数据失败, err: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览鼓掌失败!")
	}
	// 数据库获取展览
	exhibition, err := models.GetExhibition(request.ID)
	if err != nil {
		logging.Log.Errorf("数据库获取展览失败: %v\n", err.Error())
		return 400, utils.SerializeErrorData("展览鼓掌失败!")
	}
	exhibition.Applauses += 1
	models.UpdateExhibition(exhibition)

	resp := ExhibitionGiveApplauseResponse{
		Count: exhibition.Applauses,
	}
	return 200, utils.Serialize(&resp)
}
