package com.sysu.admin.api.crop;

import com.alibaba.fastjson.JSON;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.QBean;
import com.querydsl.jpa.impl.JPAQuery;
import com.sysu.admin.api.interceptor.LogAspect;
import com.sysu.admin.api.valid.ApiReqValid;
import com.sysu.admin.controller.crop.CropLand;
import com.sysu.admin.controller.crop.CropLandService;
import com.sysu.admin.controller.crop.CropPoint;
import com.sysu.admin.controller.crop.QCropLand;
import com.sysu.admin.controller.crop.images.CropImage;
import com.sysu.admin.controller.crop.images.CropImageService;
import com.sysu.admin.controller.crop.images.ImageType;
import com.sysu.admin.controller.crop.range.LandRangeIndex;
import com.sysu.admin.controller.crop.range.LandRangeIndexService;
import com.sysu.admin.controller.crop.range.QLandRangeIndex;
import com.sysu.admin.controller.geo.land.LandTaskStatus;
import com.sysu.admin.support.base.BaseComponent;
import com.sysu.admin.support.shiro.ShiroService;
import com.sysu.admin.support.system.config.SConfigService;
import com.sysu.admin.utils.shape.GeoCastUtil;
import com.xiesx.fastboot.base.result.BaseResult;
import com.xiesx.fastboot.base.result.R;
import com.xiesx.fastboot.core.token.handle.CurrentToken;
import com.xiesx.fastboot.utils.CopyUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;

@RequestMapping("/api/crop")
@RestController
public class ApiCropController extends BaseComponent {
    @Autowired
    CropLandService cityLandService;
    @Autowired
    SConfigService mSConfigService;
    @Autowired
    ShiroService mShiroService;
    @Autowired
    CropImageService cropImageService;
    @Autowired
    LandRangeIndexService landRangeIndexService;

    @RequestMapping("/table_names")
    public BaseResult tableNames(@RequestBody(required = false) String data){
        CropVo vo = JSON.parseObject(data, CropVo.class);
        if(StringUtils.isNotBlank(data) && vo.getPoint() != null) {
            String wkt = "'Point("+vo.getPoint()[0]+" "+vo.getPoint()[1]+")'";
            String sql = "select t.start,t.end,t.code,t.name,t.table_name,null as geom from p_land_range_index t where St_within(st_geomfromtext("+wkt+",4326),t.geom)";
            List<LandRangeIndex> landRangeIndices = mEntityManager.createNativeQuery(sql,LandRangeIndex.class).getResultList();
            if(landRangeIndices.size() == 0){
                LandRangeIndex defaultIndex = new LandRangeIndex();
                defaultIndex.setTableName("p_crop");
                defaultIndex.setName("其他地区");
                landRangeIndices.add(defaultIndex);
            }
            return R.succ(landRangeIndices);
        }
        QLandRangeIndex qLandRangeIndex = QLandRangeIndex.landRangeIndex;
        QBean<LandRangeIndex> selectBean = Projections.fields(qLandRangeIndex, qLandRangeIndex.code, qLandRangeIndex.name, qLandRangeIndex.tableName);
        JPAQuery<LandRangeIndex> jpaQuery = mJPAQueryFactory.select(selectBean)
                .from(qLandRangeIndex);
        return R.succ(jpaQuery.fetch());
    }

    @RequestMapping("/point_list")
    public BaseResult pointList(@RequestBody String data, @RequestHeader(value = "token",required = false) String token) throws FactoryException, TransformException {
        CropVo vo = JSON.parseObject(data, CropVo.class);
        if(vo.getMeter() > 5000){
            vo.setMeter(5000);
        }
        List<CropPoint> cropPoints = cityLandService.findByBuffer(vo.getPoint(), vo.getMeter());
        if(ObjectUtils.isNotEmpty(token)){
            Long userId = Long.valueOf(CurrentToken.getCurrentToken(token).getUserId());
            for(int i=cropPoints.size() - 1;i > -1;i--){
                if(cropPoints.get(i).getStatus().intValue() == LandTaskStatus.receive.ordinal() && !cropPoints.get(i).getReceiver().equals(userId)){
                    cropPoints.remove(i);
                }
            }
        }
        return R.succ(cropPoints);
    }

    @RequestMapping("/info")
    public BaseResult info(@RequestBody String data){
        CropVo vo = JSON.parseObject(data, CropVo.class);
        CropLand cityLand = null;
        if(vo.getId() != null) {
            cityLand = cityLandService.findOne(vo.getId());
        }else{
            cityLand = cityLandService.findByPoint(vo.getPoint());
        }
        if(cityLand == null){
            return R.fail();
        }
        cityLand.setGeojson(GeoCastUtil.gjson.toString(cityLand.getGeom()));
        List<CropImage> cropImageList = cropImageService.findByCropId(cityLand.getId());
        for(CropImage cropImage : cropImageList){
            ImageType imageType = CropImage.getImageType(cropImage.getType().intValue());
            switch (imageType){
                case fay:
                    cityLand.setFay(cropImage);
                    break;
                case center:
                    cityLand.setCenter(cropImage);
                    break;
                case near:
                    cityLand.setNear(cropImage);
                    break;
            }
        }
        return R.succ(cityLand);
    }

    @RequestMapping("/list")
    @LogAspect
    public BaseResult list(@RequestHeader("token") String token){
        CurrentToken currentToken = CurrentToken.getCurrentToken(token);
        List<Object[]> cityLandList = cityLandService.findIdAndNameByExecutor(Long.valueOf(currentToken.getUserId()));
        return R.succ(cityLandList);
    }

    @RequestMapping("/updateStatus")
    public BaseResult updateStatus(@RequestBody String data, @RequestHeader("token") String token){
        CropVo vo = JSON.parseObject(data, CropVo.class);
        vo.setToken(token);
        super.validate(vo, ApiReqValid.TokenCheckValid.class);
        CurrentToken currentToken = CurrentToken.getCurrentToken(vo.getToken());
        cityLandService.updateStatus(vo.getId(),vo.getStatus(), Long.parseLong(currentToken.getUserId()));
        return R.succ();
    }

    @PostMapping("/uploadData")
    @LogAspect
    public BaseResult uploadData(@RequestBody String json, @RequestHeader("token") String token){
        CropVo vo = JSON.parseObject(json, CropVo.class);
        vo.setToken(token);
        super.validate(vo, ApiReqValid.TokenCheckValid.class);
        CurrentToken currentToken = CurrentToken.getCurrentToken(vo.getToken());
        CropLand bean = cityLandService.findOne(vo.getId());
        BeanUtils.copyProperties(vo, bean, CopyUtils.nullNames(vo));
        bean.setExecutor(Long.parseLong(currentToken.getUserId()));
        bean.setUpdateDate(new Date());
        cityLandService.saveCropAndImages(bean);
        return R.succ();
    }


}
