import { Spec } from 'vega';

export const spec: Spec = {
  $schema: 'https://vega.github.io/schema/vega/v5.json',
  width: 900,
  height: 560,
  padding: { top: 25, left: 0, right: 0, bottom: 0 },
  autosize: 'none',

  signals: [
    {
      name: 'scale',
      value: 1200,
      bind: { input: 'range', min: 500, max: 3000 }
    },
    {
      name: 'translateX',
      value: 450,
      bind: { input: 'range', min: -500, max: 1200 }
    },
    {
      name: 'translateY',
      value: 260,
      bind: { input: 'range', min: -300, max: 700 }
    },
    {
      name: 'shape',
      value: 'line',
      bind: { input: 'radio', options: ['line', 'curve'] }
    },
    {
      name: 'hover',
      value: null,
      on: [
        { events: '@cell:pointerover', update: 'datum' },
        { events: '@cell:pointerout', update: 'null' }
      ]
    },
    {
      name: 'title',
      value: 'U.S. Airports, 2008',
      update: "hover ? hover.name + ' (' + hover.iata + ')' : 'U.S. Airports, 2008'"
    },
    {
      name: 'cell_stroke',
      value: null,
      on: [
        { events: 'dblclick', update: "cell_stroke ? null : 'brown'" },
        { events: 'pointerdown!', update: 'cell_stroke' }
      ]
    }
  ],

  data: [
    {
      name: 'states',
      url: 'data/us-10m.json',
      format: { type: 'topojson', feature: 'states' },
      transform: [
        {
          type: 'geopath',
          projection: 'projection'
        }
      ]
    },
    {
      name: 'traffic',
      url: 'data/flights-airport.csv',
      format: { type: 'csv', parse: 'auto' },
      transform: [
        {
          type: 'aggregate',
          groupby: ['origin'],
          fields: ['count'],
          ops: ['sum'],
          as: ['flights']
        }
      ]
    },
    {
      name: 'airports',
      url: 'data/airports.csv',
      format: { type: 'csv', parse: 'auto' },
      transform: [
        {
          type: 'lookup',
          from: 'traffic',
          key: 'origin',
          fields: ['iata'],
          as: ['traffic']
        },
        {
          type: 'filter',
          expr: 'datum.traffic != null'
        },
        {
          type: 'geopoint',
          projection: 'projection',
          fields: ['longitude', 'latitude']
        },
        {
          type: 'filter',
          expr: 'datum.x != null && datum.y != null'
        },
        {
          type: 'voronoi',
          x: 'x',
          y: 'y'
        },
        {
          type: 'collect',
          sort: {
            field: 'traffic.flights',
            order: 'descending'
          }
        }
      ]
    },
    {
      name: 'routes',
      url: 'data/flights-airport.csv',
      format: { type: 'csv', parse: 'auto' },
      transform: [
        {
          type: 'filter',
          expr: 'hover && hover.iata == datum.origin'
        },
        {
          type: 'lookup',
          from: 'airports',
          key: 'iata',
          fields: ['origin', 'destination'],
          as: ['source', 'target']
        },
        {
          type: 'filter',
          expr: 'datum.source && datum.target'
        },
        {
          type: 'linkpath',
          shape: { signal: 'shape' }
        }
      ]
    }
  ],

  projections: [
    {
      name: 'projection',
      type: 'albersUsa',
      scale: { signal: 'scale' },
      translate: [{ signal: 'translateX' }, { signal: 'translateY' }]
    }
  ],

  scales: [
    {
      name: 'size',
      type: 'linear',
      domain: { data: 'traffic', field: 'flights' },
      range: [16, 1000]
    }
  ],

  marks: [
    {
      type: 'path',
      from: { data: 'states' },
      encode: {
        enter: {
          fill: { value: '#dedede' },
          stroke: { value: 'white' }
        },
        update: {
          path: { field: 'path' }
        }
      }
    },
    {
      type: 'symbol',
      from: { data: 'airports' },
      encode: {
        enter: {
          size: { scale: 'size', field: 'traffic.flights' },
          fill: { value: 'steelblue' },
          fillOpacity: { value: 0.8 },
          stroke: { value: 'white' },
          strokeWidth: { value: 1.5 }
        },
        update: {
          x: { field: 'x' },
          y: { field: 'y' }
        }
      }
    },
    {
      type: 'path',
      name: 'cell',
      from: { data: 'airports' },
      encode: {
        enter: {
          fill: { value: 'transparent' },
          strokeWidth: { value: 0.35 }
        },
        update: {
          path: { field: 'path' },
          stroke: { signal: 'cell_stroke' }
        }
      }
    },
    {
      type: 'path',
      interactive: false,
      from: { data: 'routes' },
      encode: {
        enter: {
          path: { field: 'path' },
          stroke: { value: 'black' },
          strokeOpacity: { value: 0.35 }
        }
      }
    },
    {
      type: 'text',
      interactive: false,
      encode: {
        enter: {
          x: { value: 895 },
          y: { value: 0 },
          fill: { value: 'black' },
          fontSize: { value: 20 },
          align: { value: 'right' }
        },
        update: {
          text: { signal: 'title' }
        }
      }
    }
  ]
};
