<script>
  // a custom slider for time range selection
  import { createEventDispatcher } from 'svelte';
  import { scaleLinear, scaleTime } from 'd3-scale';
  import { slidable } from '../../actions/slidable';
  import { timeRangeFilter, fullTimeRange, defaultTimeRange } from '../../stores/filters';

  export let lockInMode = false;
  export let label = '';
  export let showLabel = true;
  export let min = 0;
  export let max = 10;
  export let value;
  export let showHandleLabels = true;
  export let startColor = 'white';
  export let middleColor = null;
  export let stopColor = 'rgb(255, 0, 0)';
  export let barOpacity = 1;
  export let showBorder = true;

  // Convert the numeric value numbers to dates
  $: convertScale = scaleTime().domain($defaultTimeRange).range(value)

  const dispatch = createEventDispatcher();
  const handleWidth = 17;

  const pos = {
    left: 0,
    right: 0
  };

  let sliderWidth = 0;

  function handleSlide(e, side) {
    const newPos = pos[side] + e.detail.dx;

    if (newPos < 0 || newPos > sliderWidth) return;
    if (side === 'left' && newPos > pos.right) return;
    if (side === 'left' && newPos < scale.range()[0]) return;
    if (side === 'right' && newPos < pos.left) return;
    if (side === 'right' && newPos > scale.range()[1]) return;
    
    pos[side] = newPos;
  }

  function handleSlideEnd(e, side) {
    if (lockInMode) {
      dispatch('changed', [Math.round(scale.invert(pos.left), 0),
                         Math.round(scale.invert(pos.right), 0)]);
    } else {
      dispatch('changed', [scale.invert(pos.left), scale.invert(pos.right)]);
      $timeRangeFilter = [convertScale.invert(scale.invert(pos.left)), convertScale.invert(scale.invert(pos.right))]
    }
  }

  $: scale = scaleLinear()
      .domain([min, max])
      .range([handleWidth / 2, sliderWidth - 1.7 * handleWidth]);

  $: pos.left = scale(value[0]) || 0;
  $: pos.right = scale(value[1]) || 0;

  $: background = `linear-gradient(90deg, ${startColor}, ${middleColor ? middleColor + ', ' : ''}${stopColor})`;
  //$: background = `linear-gradient(90deg, #ffffff, #000000)`;
</script>

<div class="slider"
     bind:clientWidth={sliderWidth}
     style="--handle-width: {handleWidth}px;">
  {#if (showLabel)}
    <div class="label">
      {label}
    </div>
  {/if}
  <div class="slider-body" class:border={showBorder}>
    <div class="slider-selected-range"
         style="width: {sliderWidth - 2 * handleWidth}px;
                margin-left: {1 * handleWidth}px;
                opacity: {barOpacity};
                background: {background};"></div>
    <div class="slider-handle"
         class:no-label={!showHandleLabels}
         style="left: {(Math.abs(value[0] - value[1]) < 0.1) ? pos.left - 5 : pos.left}px;"
         use:slidable
         on:slide={(e) => handleSlide(e, 'left')}
         on:slideend={(e) => handleSlideEnd(e, 'left')}>
      <span class="disable-select">{showHandleLabels ? Math.round(scale.invert(pos.left), 0) : ''}</span>
    </div>
    <div class="slider-handle"
         class:no-label={!showHandleLabels}
         style="left: {(Math.abs(value[0] - value[1]) < 0.1) ? pos.right + 5 : pos.right}px;"
         use:slidable
         on:slide={(e) => handleSlide(e, 'right')}
         on:slideend={(e) => handleSlideEnd(e, 'right')}>
      <span class="disable-select">{showHandleLabels ? Math.round(scale.invert(pos.right), 0) : ''}</span>
    </div>
  </div>
</div>

<style>
  .slider {
    display: flex;
    flex-direction: column;
    font-family: var(--font-02);
    width: 200px;
    max-width: 200px;
    margin: 0.3rem 0.3rem 0 0.3rem;
    position: relative;
    pointer-events: all;
  }

  .label {
    margin: 0 0 0.1rem 0;
    font-size: 0.7rem;
    color: var(--usa-blue);
  }

  .slider-body {
    display: flex;
    align-items: center;
    width: 100%;
    height: 1.7rem;
    padding: 0.1rem 0;
    font-size: 0.7rem;
    background-color: var(--bg);
    border: none;
    position: relative;
  }

  .border {
    border: 2px solid var(--usa-blue);
    border-radius: 3px;
  }

  .slider-selected-range {
    height: 8px;
    border: none;
    border-radius: 2px;
    position: absolute;
    z-index: 100;
  }

  .slider-handle {
    width: var(--handle-width);
    height: var(--handle-width);
    border: 2px solid var(--usa-blue);
    border-radius: 50%;
    background-color: var(--bg);
    cursor: pointer;
    position: absolute;
    z-index: 10000;
  }

  .slider-handle > span {
    width: 100%;
    height: 100%;
    font-size: 0.7rem;
    text-align: center;
    color: var(--usa-blue);
    position: absolute;
  }
</style>
