import { Spec } from 'vega';

export const spec: Spec = {
  $schema: 'https://vega.github.io/schema/vega/v5.json',
  width: 400,
  height: 200,
  padding: 5,
  autosize: { type: 'fit', resize: true },

  signals: [
    {
      name: 'maxbins',
      value: 10,
      bind: { input: 'select', options: [5, 10, 20] }
    },
    {
      name: 'binCount',
      update: '(bins.stop - bins.start) / bins.step'
    },
    {
      name: 'nullGap',
      value: 10
    },
    {
      name: 'barStep',
      update: '(width - nullGap) / (1 + binCount)'
    }
  ],

  data: [
    {
      name: 'table',
      url: 'data/movies.json',
      transform: [
        {
          type: 'extent',
          field: 'IMDB Rating',
          signal: 'extent'
        },
        {
          type: 'bin',
          signal: 'bins',
          field: 'IMDB Rating',
          extent: { signal: 'extent' },
          maxbins: { signal: 'maxbins' }
        }
      ]
    },
    {
      name: 'counts',
      source: 'table',
      transform: [
        {
          type: 'filter',
          expr: "datum['IMDB Rating'] != null"
        },
        {
          type: 'aggregate',
          groupby: ['bin0', 'bin1']
        }
      ]
    },
    {
      name: 'nulls',
      source: 'table',
      transform: [
        {
          type: 'filter',
          expr: "datum['IMDB Rating'] == null"
        },
        {
          type: 'aggregate'
        }
      ]
    }
  ],

  scales: [
    {
      name: 'yscale',
      type: 'linear',
      range: 'height',
      round: true,
      nice: true,
      domain: {
        fields: [
          { data: 'counts', field: 'count' },
          { data: 'nulls', field: 'count' }
        ]
      }
    },
    {
      name: 'xscale',
      type: 'linear',
      range: [{ signal: 'barStep + nullGap' }, { signal: 'width' }],
      round: true,
      domain: { signal: '[bins.start, bins.stop]' },
      bins: { signal: 'bins' }
    },
    {
      name: 'xscale-null',
      type: 'band',
      range: [0, { signal: 'barStep' }],
      round: true,
      domain: [null]
    }
  ],

  axes: [
    { orient: 'bottom', scale: 'xscale', tickCount: 10, zindex: 1 },
    { orient: 'bottom', scale: 'xscale-null', zindex: 1 },
    { orient: 'left', scale: 'yscale', tickCount: 5, offset: 5, zindex: 1 }
  ],

  marks: [
    {
      type: 'rect',
      from: { data: 'counts' },
      encode: {
        update: {
          x: { scale: 'xscale', field: 'bin0', offset: 1 },
          x2: { scale: 'xscale', field: 'bin1' },
          y: { scale: 'yscale', field: 'count' },
          y2: { scale: 'yscale', value: 0 },
          fill: { value: 'steelblue' }
        },
        hover: {
          fill: { value: 'firebrick' }
        }
      }
    },
    {
      type: 'rect',
      from: { data: 'nulls' },
      encode: {
        update: {
          x: { scale: 'xscale-null', value: null, offset: 1 },
          x2: { scale: 'xscale-null', band: 1 },
          y: { scale: 'yscale', field: 'count' },
          y2: { scale: 'yscale', value: 0 },
          fill: { value: '#aaa' }
        },
        hover: {
          fill: { value: 'firebrick' }
        }
      }
    }
  ]
};
