import _ from 'lodash'
import { formatDate, getAnnotationFeature } from '../util'
import {mapStyle, layerFolders} from '../constants'
import * as turf from '@turf/turf'
import mapboxgl from 'mapbox-gl'
mapboxgl.accessToken =
  'pk.eyJ1Ijoid2FueWFueWFuIiwiYSI6Im1uNVZnTncifQ.90XY40_yjpItUHO8HnbbpA'

export async function generateReport (params) {
  let {projectInfo, taskInfo, annotations} = params
  return {
    title: '标注报告',
    projectName: projectInfo.name,
    taskName: taskInfo.name,
    user_id: taskInfo.user_id,
    project_id: taskInfo.project_id,
    task_id: taskInfo.task_id,
    data_type: taskInfo.data_type,
    sections: [
      {
        title: '任务概览',
        content: [
          {
            type: 'form',
            items: getTaskPreview(taskInfo)
          },
          {
            type: 'image',
            imageType: 'overview'
          }
        ]
      },
      {
        title: '标注列表',
        content: [
          {
            type: 'sub-title',
            label: '点标注'
          },
          {
            type: 'annotation-list',
            colums: getPointColums(taskInfo.data_type),
            data: getAnnoData(annotations, 'point')
          },
          {
            type: 'sub-title',
            label: '线标注'
          },
          {
            type: 'annotation-list',
            colums: getLineColums(taskInfo.data_type),
            data: getAnnoData(annotations, 'line')
          },
          {
            type: 'sub-title',
            label: '面标注'
          },
          {
            type: 'annotation-list',
            colums: getPolygonColums(taskInfo.data_type),
            data: getAnnoData(annotations, 'polygon')
          },
          {
            type: 'page-line'  // 分页
          }
        ]
      },
      {
        title: '标注详情',
        content: [
          {
            type: 'details',
            data: getAnnotationDetails(annotations, taskInfo)
          }
        ]
      }
    ]
  }
}

function getTaskPreview (taskInfo) {
  return [
    {
      label: '任务名称',
      value: taskInfo.name
    },
    {
      label: '任务类型',
      value: getDataType(taskInfo.data_type)
    },
    {
      label: '数据采集时间',
      value: formatDate(taskInfo.captured_at)
    },
    {
      label: '重建时间',
      value: formatDate(taskInfo.completed_at)
    }
  ]
}

function getDataType (type) {
  if (type === 'infrared') {
    return '热红外'
  } else if (type === 'multispectral') {
    return '多光谱'
  } else {
    return '可见光'
  }
}

function getPointColums (data_type) {
  return [
    {
      title: '',
      slot: 'color',
      key: 'color',
      width: 100
    },
    {
      title: '名称',
      key: 'name'
    },
    {
      title: '经度（X）',
      key: 'x'
    },
    {
      title: '纬度（Y）',
      key: 'y'
    },
    {
      title: data_type === 'infrared' ? '温度（℃）' : '高度（Z）',
      key: data_type === 'infrared' ? 'temprature' : 'height'
    }
  ]
}

function getLineColums (data_type) {
  if (data_type === 'infrared') {
    return [
      {
        title: '',
        slot: 'color',
        key: 'color',
        width: 100
      },
      {
        title: '名称',
        key: 'name'
      },
      {
        title: '长度（m）',
        key: 'distance2d'
      },
      {
        title: '最低温度（℃）',
        key: 'temprature_min'
      },
      {
        title: '最高温度（℃）',
        key: 'temprature_max'
      }
    ]
  } else {
    return [
      {
        title: '',
        slot: 'color',
        key: 'color',
        width: 100
      },
      {
        title: '名称',
        key: 'name'
      },
      {
        title: '2D长度（m）',
        key: 'distance2d'
      },
      {
        title: '3D长度（m）',
        key: 'distance3d'
      },
      {
        title: '最小坡度（°）',
        key: 'slope_min'
      },
      {
        title: '最大坡度（°）',
        key: 'slope_max'
      },
      {
        title: '最小高度（m）',
        key: 'height_min'
      },
      {
        title: '最大高度（m）',
        key: 'height_max'
      }
    ]
  }
}

function getPolygonColums (data_type) {
  if (data_type === 'infrared') {
    return [
      {
        title: '',
        slot: 'color',
        key: 'color',
        width: 100
      },
      {
        title: '名称',
        key: 'name'
      },
      {
        title: '面积（㎡）',
        key: 'area2d'
      },
      {
        title: '周长（m）',
        key: 'distance2d'
      },
      {
        title: '最低温度（℃）',
        key: 'temprature_min'
      },
      {
        title: '最高温度（℃）',
        key: 'temprature_max'
      }
    ]
  } else {
    return [
      {
        title: '',
        slot: 'color',
        key: 'color',
        width: 100
      },
      {
        title: '名称',
        key: 'name'
      },
      {
        title: '2D面积（㎡）',
        key: 'area2d'
      },
      {
        title: '3D面积（㎡）',
        key: 'area3d'
      },
      {
        title: '2D周长（m）',
        key: 'distance2d'
      },
      {
        title: '3D周长（m）',
        key: 'distance3d'
      },
      {
        title: '最小高度（m）',
        key: 'height_min'
      },
      {
        title: '最大高度（m）',
        key: 'height_max'
      }
    ]
  }
}

function getAnnoData (annotations, type) {
  return annotations.filter(d => d.type === type).map(d => {
    let obj = _.cloneDeep(d)
    if (type === 'point') {
      let coord = d.geometry.coordinates
      obj.x = _.round(coord[0], 6)
      obj.y = _.round(coord[1], 6)
    }
    delete obj.geometry
    return obj
  })
}

function getAnnotationDetails (annotations, taskInfo) {
  let {data_type} = taskInfo
  let colums = {
    point: getPointColums(data_type),
    line: getLineColums(data_type),
    polygon: getPolygonColums(data_type)
  }
  let sortIndex = {point: 1, line: 2, polygon: 3}
  let sorted = annotations.sort((a, b) => sortIndex[a.type] - sortIndex[b.type])
  let items = []
  let features = []
  sorted.forEach(anno => {
    let {id, type, name, color} = anno
    let data = {}
    colums[type].forEach(col => {
      if (col.key === 'color' || col.key === 'name') {
        return
      }
      if (type === 'point') {
        let coord = anno.geometry.coordinates
        anno.x = _.round(coord[0], 6)
        anno.y = _.round(coord[1], 6)
      }
      data[col.title] = anno[col.key]
    })
    let feature = getAnnotationFeature(anno)
    features.push(feature)
    items.push({
      id, 
      name,
      type,
      color,
      data,
      feature,
      image: ''
    })
  })
  return items
}

function getStyle (features, report) {
  let style = _.cloneDeep(mapStyle)
  style.layers.push({
    id: 'background',
    type: 'background',
    paint: {
      'background-color': '#000000'
    }
  })
  let {taskName, projectName, user_id, data_type} = report
  let type = data_type === 'infrared' ? 'tmp' : 'dom'
  let tileUrl = `http://127.0.0.1:10024/${user_id}/${projectName}/${taskName}/result/2D/${layerFolders[type]}/{z}/{x}/{y}.webp`
  style.sources.dom_image = {
    'type': 'raster',
    'tiles': [ tileUrl ],
    'tileSize': 512
  }
  style.sources.annotation = {
    type: 'geojson',
    data: {
      type: 'FeatureCollection',
      features
    }
  }
  style.layers.push({
    'id': 'dom_image',
    'source': 'dom_image',
    'type': 'raster'
  })
  style.layers.push({
    'id': 'annotation-point',
    'type': 'circle',
    filter: ['==', '$type', 'Point'],
    source: 'annotation',
    'paint': {
      'circle-radius': 10,
      'circle-color': ['get', 'color']
    }
  })
  style.layers.push({
    'id': 'annotation-line',
    'type': 'line',
    filter: ['!=', '$type', 'Point'],
    source: 'annotation',
    'layout': {
      'line-cap': 'round',
      'line-join': 'round'
    },
    'paint': {
      'line-color': ['get', 'color'],
      'line-width': 4
    }
  })
  style.layers.push({
    'id': 'annotation-polygon',
    'type': 'fill',
    filter: ['==', '$type', 'Polygon'],
    source: 'annotation',
    'paint': {
      'fill-color': ['get', 'color'],
      'fill-opacity': 0.1
    }
  })
  return style
}

export function initMap (features, report) {
  return new Promise((resolve) => {
    let style = getStyle(features, report)
    let div = document.createElement('div')
    div.style.width = '800px'
    div.style.height = '400px'
    div.style.position = 'absolute'
    div.style.zIndex = '-1'
    document.body.appendChild(div)
    let map = new mapboxgl.Map({
      container: div,
      style: style,
      bearing: 0,
      pitch: 0,
      center: [110.9, 32.79],
      zoom: 4.2,
      interactive: true,
      doubleClickZoom: false,
      dragRotate: false,
      pitchWithRotate: false,
      preserveDrawingBuffer: true,
      localFontFamily: 'sans-serif'
    })
    map.on('load', () => {
      resolve(map)
    })
  })
  
}

export function removeMap (map) {
  map.remove()
  document.body.removeChild(map.getContainer())
}

export function getImage (map, feature) {
  let extent = turf.bbox(feature)
  let {id} = feature.properties
  map.fitBounds(extent, {
    animate: false,
    padding: 50,
    maxZoom: 19
  })
  map.setFilter('annotation-point', ['all', ['==', '$type', 'Point'], ['==', 'id', id]])
  map.setFilter('annotation-line', ['all', ['!=', '$type', 'Point'], ['==', 'id', id]])
  map.setFilter('annotation-polygon', ['all', ['==', '$type', 'Polygon'], ['==', 'id', id]])
  return new Promise((resolve) => {
    map.once('idle', () => {
      let canvas = map.getCanvas()
      resolve(canvas.toDataURL('image/png'))
    })
  })
}