import { useAppStoreWithOut } from '@/store/modules/app'
import { diceCode } from '@/utils'
import tunnelConfigs from '@/config/tunnel'

const appStore = useAppStoreWithOut()

const CAR_TYPES = {
  '01': { length: 120 },
  '02': { length: 120 },
  '03': { length: 120 },
  '04': { length: 120 }
}

class Car {

  id // 车辆 ID
  type // 车型
  speed // 车速
  time // 瞬时记录
  car_length // 车身长
  car_width // 车身宽
  new_car = false

  distance = 0 // 行驶距离（米）
  x = 0 // 横向位置 px
  y // 纵向位置 px
  
  line // 行驶车道
  direction // 行驶方向

  lanes = [] // 车道行驶线
  ratex = 1 // 换算比
  animate_time = 1 // 动画间隔

  constructor (configs) {

    const {
      id, type, speed, distance, line, direction,
      car_length, car_width, new_car = false, 
      ratex, lanes
    } = configs

    this.id = id
    this.type = type
    this.speed = speed
    this.line = line
    this.direction = direction
    this.car_length = car_length
    this.car_width = car_width
    
    this.lanes = lanes
    this.ratex = ratex
    this.new_car = new_car
    this.x = new_car ? 0 : distance * this.ratex * (direction ? 1 : -1)
    this.y = lanes[line - 1] - car_width / 2
    this.time = (new Date()).getTime()

    this.style = {
      transform: `translate(${this.x}px, ${this.y}px)`
    }

  }

  run (e) {

    const { speed, line, distance } = e

    this.speed = speed
    this.line = line
    this.distance = distance

    this.x = distance * this.ratex * (this.direction ? 1 : -1)
    this.y = this.lanes[line - 1] - this.car_width / 2
    this.time = (new Date()).getTime()

    if (this.new_car) {
      this.style = {
        transform: `translate(0px, ${this.y}px)`
      }
    } else {
      this.style = {
        transform: `translate(${this.x}px, ${this.y}px)`,
        transitionProperty: 'all',
        transitionDuration: '1s',
        transitionTimingFunction: 'linear'
      }
    }

  }

}

class TrafficEngine {

  engine = null
  run_x = 0 // 运行计数

  ratex = 1 // 换算比
  miles = 3200 // 隧道总长
  section = tunnelConfigs.perSection // 段面长

  lanes = 2 // 车道数
  lane_w = 135 // 车道宽
  drive_lines = [] // 车道行驶线
  tracker = null // 追踪器
  
  cars = [] // 路面车流
  mook_sign = null // 模拟器签名

  constructor (configs) {

    this.ratex = appStore.getDesign / this.section
    this.drive_lines = new Array(this.lanes).fill(null).map((_, x) => {
      return (x + 0.5) * this.lane_w + (this.lane_w % 2 === 0 ? -0.5 : 0) // 1/2 车道宽为奇数时正好居中，为偶数时需要补 0.5px
    })

  }


  // 车辆追踪
  startTrack (tracker) {
    this.tracker = tracker
  }

  // 更新车流
  carUpdate (cars) {

    const currentMap = Object.fromEntries(cars.map(item => {
      return [item.id, item]
    }))

    // 出隧道缓存清理
    this.cars = this.cars.filter(item => item.distance < this.miles && currentMap[item.id] )

    // 旧车更新
    this.cars.forEach(item => {

      if (currentMap[item.id]) {
        item.run(currentMap[item.id])
      }

    })

    // 新车汇入

    const newCars = cars
      .filter(xcar => !this.cars.some(item => item.id === xcar.id))
      .map(item => {
        return new Car({
          ...item, new_car: true, lanes: this.drive_lines, ratex: this.ratex
        })
      })

    this.cars = this.cars.concat(newCars)
    this.run_x++

    if (this.tracker && this.cars.length > 2) {
      Object.assign(this.tracker, {
        ...this.cars[2]
      }) 
    }

  }

  // 虚实现换算
  lineFormate (lines) {

    return lines.map(({start, end, type}) => {
      
      return {
        x: start * this.ratex,
        type,
        long: (end - start) * this.ratex
      }

    })

  }

  // 摄像机换算
  cameraFormate (cameras) {

    return cameras.map(({ point, name, avgspeed, act }) => {

      const pileNumber = 'K' + (point - (point % 1000)) / 1000 + '+' + point % 1000

      return {
        x: point * this.ratex,
        name,
        act,
        pileNumber,
        avgspeed
      }
    })

  }

  // 事件换算
  eventFormate (events) {
    return events.map(item => {
      return {
        x: (item.milestone % 2600) * this.ratex,
        y: this.drive_lines[item.eventRoadNo - 1],
        transform: `translate(${item.direction ? '-50%' : '50%'}, ${item.direction ? '50%' : '-50%'})`,
        ...item
      }
    })
  }

  // 设施缓存
  facilitiesFormate (facilities) {

    return facilities.map(({ start, end, type, direction }) => {
      return {
        x: start * this.ratex,
        type,
        direction
      }
    })

  }

  // 缎面计算
  sectionsCompute () {

    const leftMiles = this.miles % this.section
    const completeSections = (this.miles - leftMiles) / this.section

    return (new Array(completeSections + (leftMiles > 0 ? 1 : 0))).fill(null).map((_, x) => {
      return {
        grow: x < completeSections ? 1 : leftMiles / this.section
      }
    })

  }

  // 车流模拟
  startMook () {

    this.mook_sign && clearInterval(this.mook_sign)

    let cars = []
    let count = 0

    this.mook_sign = setInterval(() => {

      cars.forEach(item => {
        item.distance = ((item.speed * 1000) / (3600 * 12)) + item.distance
        item.line = Math.random() > 0.999 ? (3 - item.line) : item.line
      })

      cars = cars.filter(item => item.distance < this.miles )

      const type = '0' + parseInt(Math.random() * 4 + 1),
      speed = parseInt(120 + Math.random() * 30),
      line = Math.random() > 0.5 ? 2 : 1,
      direction = 0

      count ++ 

      if (count % 60 === 0) {
        cars.push({
          type, speed, line, direction,
          id: diceCode(),
          distance: 0,
          car_width: 40,
          car_length: 120
        })
      }

      
      this.carUpdate(cars)

    }, 83)
    



  }

  // 车流供给
  exportCars () {

    return this.cars.map(item => {
      return {
        id: item.id,
        type: item.type,
        style: item.style,
        direction: item.direction,
        originalCar: item.originalCar
      }
    })

    this.cars.forEach(item => {
      item.new_car = false
    })

  }

}


export default TrafficEngine