package com.microservices.zone.common.service.impl;

import com.microservices.common.core.exception.ServiceException;
import com.microservices.zone.common.service.IZoneSortService;
import com.microservices.zone.detail.domain.ZoneSort;
import com.microservices.zone.detail.mapper.ZoneSortMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author otto
 */
@Service
public class ZoneSortServiceImpl implements IZoneSortService {
    private static final Logger logger = LoggerFactory.getLogger(ZoneSortServiceImpl.class);
    @Autowired
    private ZoneSortMapper zoneSortMapper;

    @Override
    public Integer setSortByOrder(ZoneSort data, Integer order, String tableName) {
        return setSortByOrder(data, order, tableName, true);
    }

    @Override
    public Integer setSortByDescOrder(ZoneSort data, Integer order, String tableName) {
        return setSortByOrder(data, order, tableName, false);
    }


    public Integer setSortByOrder(ZoneSort data, Integer order, String tableName, boolean isAsc) {
        Integer setSort;
        Long zoneId = data.getZoneId();
        Long id = data.getId();
        Integer maxCount = zoneSortMapper.selectCountByZoneId(zoneId, tableName);
        //检查用户输入顺序是否合法
        if (order < 1 || order > maxCount) {
            throw new ServiceException(String.format("顺序最小为1，最大为%d(id[%s])", maxCount, id));
        }
        //获取所在行
        ZoneSort theOrderContainSelf = zoneSortMapper.selectDataByOrderAndZoneId(data, order, true, tableName, isAsc);
        //当指定序号为当前数据时，不修改排序
        if (theOrderContainSelf != null && theOrderContainSelf.getId().equals(id)) {
            return null;
        }

        if (order == 1 || order.equals(maxCount)) {
            int minSort = zoneSortMapper.selectMinSortByZoneId(zoneId, tableName);
            int maxSort = zoneSortMapper.selectMaxSortByZoneId(zoneId, tableName);
            //当用户输入顺序为1时，降序顺序调整为最大值+1.升序顺序调整为最小值-1
            if (order == 1) {
                setSort = isAsc ? (minSort - 1) : (maxSort + 1);
            } else {
                //当用户输入顺序为列表总数时，降序顺序调整为最小值-1.升序顺序调整为最大值+1
                setSort = isAsc ? (maxSort + 1) : (minSort - 1);
            }
        } else {
            //获取指定序号的数据(不包含当前数据)
            ZoneSort theOrderData = zoneSortMapper.selectDataByOrderAndZoneId(
                    data, order, false, tableName, isAsc);
            if (theOrderData == null) {
                throw new ServiceException(String.format("指定顺序不存在(id[%s]，顺序[%d])", id, order));
            }
            //计算用户上一个序号对应的排序值(不包含当前数据)
            ZoneSort theLastOrderData = zoneSortMapper.selectDataByOrderAndZoneId(
                    data, order - 1, false, tableName, isAsc);
            Integer theLastSort = theLastOrderData.getSort();
            if (isAsc) {
                if (theOrderData.getSort() - theLastSort > 1) {
                    setSort = theLastSort + 1;
                } else {
                    setSort = theOrderData.getSort();
                    //需要将大于等于该sort的所有数据项sort+1
                    Integer updateCount = zoneSortMapper.batchUpdateSortIncreased(zoneId, setSort, tableName);
                    logger.info("批量增加大于指定排序的排序值，共计更新{}条", updateCount);
                }
            } else {
                if (theOrderData.getSort() - theLastSort > 1) {
                    setSort = theLastSort - 1;
                } else {
                    setSort = theOrderData.getSort();
                    //需要将小于于等于该sort的所有数据项sort-1
                    Integer updateCount = zoneSortMapper.batchUpdateSortDecrease(zoneId, setSort, tableName);
                    logger.info("批量减少小于指定排序的排序值，共计更新{}条", updateCount);
                }
            }

        }
        return setSort;
    }

    @Override
    public Integer getMaxSort(Long zoneId, String tableName) {
        //设置排序值为当前最大的排序值+1
        Integer maxSort = zoneSortMapper.selectMaxSortByZoneId(zoneId, tableName);
        if (maxSort == null) {
            maxSort = 1;
        } else {
            maxSort++;
        }
        return maxSort;
    }
}
