package com.red.circle.other.infra.database.mongo.service.game.impl;

import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameLudoPlayer;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameLudoRun;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameStatus;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameStatusEvent;
import com.red.circle.other.infra.database.mongo.service.game.GameLudoRunService;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

/**
 * 飞行棋游戏服务 实现.
 *
 * @author pengliang on 2022/3/8
 */
@Service
@RequiredArgsConstructor
public class GameLudoRunServiceImpl implements GameLudoRunService {

  private final MongoTemplate mongoTemplate;

  @Override
  public List<GameLudoRun> flowSelective(String sysOrigin, Long roomId, Long lastId) {
    Criteria criteria = new Criteria();
    if (StringUtils.isNotBlank(sysOrigin)) {
      criteria.and("sysOrigin").is(sysOrigin);
    }
    if (Objects.nonNull(roomId)) {
      criteria.and("roomId").is(roomId);
    }
    if (Objects.nonNull(lastId)) {
      criteria.and("id").lt(lastId);
    }
    return mongoTemplate.find(Query.query(criteria)
            .with(Sort.by(Sort.Order.desc("id")))
            .limit(PageConstant.DEFAULT_LIMIT_SIZE),
        GameLudoRun.class);
  }

  @Override
  public GameLudoRun get(Long id) {
    return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), GameLudoRun.class);
  }

  @Override
  public boolean create(GameLudoRun gameLudoRun) {
    gameLudoRun.setId(gameLudoRun.getRoomId());
    gameLudoRun.setCreateTime(TimestampUtils.now());
    if (exists(gameLudoRun.getId())) {
      return false;
    }
    mongoTemplate.save(gameLudoRun);
    return true;
  }

  @Override
  public void resetPlayers(Long id, List<GameLudoPlayer> players) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
        new Update().set("players", players), GameLudoRun.class);
  }

  @Override
  public void updateGameStatus(Long id, GameStatus gameStatus, GameStatusEvent gameStatusEvent) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
        new Update().set("gameStatus", gameStatus)
            .set("gameStatusEvent", gameStatusEvent), GameLudoRun.class);
  }

  @Override
  public boolean exists(Long id) {
    return mongoTemplate.exists(Query.query(Criteria.where("id").is(id)),
        GameLudoRun.class);
  }

  @Override
  public List<GameLudoRun> listByRoomIds(List<Long> roomIds) {
    if (roomIds == null || roomIds.isEmpty()) {
      return List.of();
    }
    return mongoTemplate.find(
        Query.query(Criteria.where("id").in(roomIds)),
        GameLudoRun.class);
  }

  @Override
  public void remove(Long id) {
    mongoTemplate.remove(Query.query(Criteria.where("id").is(id)), GameLudoRun.class);
    mongoTemplate.remove(Query.query(Criteria.where("roomId").is(String.valueOf(id))),
        "game_ludo_run_detail");
  }

}
