import * as calculator from './calculator';
import { TimelineState } from '../../types';

describe('calculator with samplesPerPx 100, padding 100, scrollLeft 25, duration 48000, viewportWidth 300', () => {
  const state: TimelineState = {
    viewportWidth: 300,
    samplesPerPx: 100,
    padding: 10,
    scrollLeft: 50,
    duration: 48000
  }

  describe('samplesToPx', () => {
    it('given 0, returns 0', () => {
      expect(calculator.samplesToPx(state, 0)).toBe(0);
    });
    it('given 100, returns 1', () => {
      expect(calculator.samplesToPx(state, 100)).toBe(1);
    });
    it('given -50, returns -0.5', () => {
      expect(calculator.samplesToPx(state, -50)).toBe(-0.5);
    });
  });

  describe('pxToSamples', () => {
    it('given 0, returns 0', () => {
      expect(calculator.pxToSamples(state, 0)).toBe(0);
    });
    it('given 0.5, returns 50', () => {
      expect(calculator.pxToSamples(state, 0.5)).toBe(50);
    });
    it('given -1, returns -100', () => {
      expect(calculator.pxToSamples(state, -1)).toBe(-100);
    });
  });


  describe('viewportPxToSamples', () => {
    it('given 0, returns 4000', () => {
      expect(calculator.viewportPxToSamples(state, 0)).toBe(4000);
    });
    it('given -40, returns 0', () => {
      expect(calculator.viewportPxToSamples(state, -40)).toBe(0);
    });
  });

  describe('samplesToViewportPx', () => {
    it('given 0, returns -40', () => {
      expect(calculator.samplesToViewportPx(state, 0)).toBe(-40);
    });
    it('given 6300, returns 23', () => {
      expect(calculator.samplesToViewportPx(state, 6300)).toBe(23);
    });
  });

  describe('getContentWidth', () => {
    it('returns 500', () => {
      expect(calculator.getContentWidth(state)).toBe(500);
    });
  });

  describe('getFocusWidth', () => {
    it('returns 280', () => {
      expect(calculator.getFocusWidth(state)).toBe(280);
    });
  });

  describe('clampScrollLeft', () => {
    it('given 0, returns 0', () => {
      expect(calculator.clampScrollLeft(state, 0)).toBe(0);
    });
    it('given -100, returns 0', () => {
      expect(calculator.clampScrollLeft(state, -100)).toBe(0);
    });
    it('given 200, returns 200', () => {
      expect(calculator.clampScrollLeft(state, 200)).toBe(200);
    });
    it('given 201, returns 200', () => {
      expect(calculator.clampScrollLeft(state, 201)).toBe(200);
    });
    it('given 150, returns 150', () => {
      expect(calculator.clampScrollLeft(state, 150)).toBe(150);
    });
  });

  describe('reducers', () => {
    describe('scroll', () => {
      it('given 0, returns an equal state', () => {
        expect(calculator.scroll(state, 0)).toEqual(state);
      });
      it('given -50, returns a state with scrollLeft 0', () => {
        expect(calculator.scroll(state, -50).scrollLeft).toBe(0);
      });
      it('given 50, returns a state with scrollLeft 50', () => {
        expect(calculator.scroll(state, 50).scrollLeft).toBe(100);
      });
      it('clamps: given 5000, returns a state with scrollLeft 200', () => {
        expect(calculator.scroll(state, 5000).scrollLeft).toBe(200);
      });
      it('clamps: given -100, returns a state with scrollLeft 0', () => {
        expect(calculator.scroll(state, -100).scrollLeft).toBe(0);
      });
    });

    describe('showBounds', () => {
      it('given 0 and 2800, returns a state with scrollLeft 0 and samplesPerPx 10', () => {
        expect(calculator.showBounds(state, 0, 2800)).toEqual({ ...state, scrollLeft: 0, samplesPerPx: 10 });
      });

      it('given 1400 and 2800, returns a state with scrollLeft 280 and samplesPerPx 5', () => {
        expect(calculator.showBounds(state, 1400, 2800)).toEqual({ ...state, scrollLeft: 280, samplesPerPx: 5 });
      });

      it('given 0 and 28000, returns a state with scrollLeft 0 and samplesPerPx = 100', () => {
        expect(calculator.showBounds(state, 0, 28000)).toEqual({ ...state, scrollLeft: 0, samplesPerPx: 100 });
      });
    });

    describe('showPoint', () => {
      it('given 0, returns a state with scrollLeft 0', () => {
        expect(calculator.showPoint(state, 0).scrollLeft).toBe(0);
      });
      it('given 14000, returns a state with scrollLeft 0', () => {
        expect(calculator.showPoint(state, 14000).scrollLeft).toBe(0);
      });
      it('given 14100, returns a state with scrollLeft 1', () => {
        expect(calculator.showPoint(state, 14100).scrollLeft).toBe(1);
      });
      it('given 24000, returns a state with scrollLeft 100', () => {
        expect(calculator.showPoint(state, 24000).scrollLeft).toBe(100);
      });
      it('given 34000, returns a state with scrollLeft 200', () => {
        expect(calculator.showPoint(state, 34000).scrollLeft).toBe(200);
      });
      it('given 33900, returns a state with scrollLeft 199', () => {
        expect(calculator.showPoint(state, 33900).scrollLeft).toBe(199);
      });
      it('given 48000, returns a state with scrollLeft 200', () => {
        expect(calculator.showPoint(state, 48000).scrollLeft).toBe(200);
      });
    });

    describe('scaleByFactor', () => {
      it('given 1, returns an identical state', () => {
        expect(calculator.scaleByFactor(state, 1)).toEqual(state);
      });
      it('given 2, returns a state with scrollLeft 0 and samplesPerPx 200', () => {
        expect(calculator.scaleByFactor(state, 0.5)).toEqual({ ...state, scrollLeft: 0, samplesPerPx: 200 });
      });
      it('given 1/1.1, returns a state with scrollLeft 35 and samplesPerPx 110', () => {
        expect(calculator.scaleByFactor(state, 1/1.1)).toEqual({ ...state, scrollLeft: 35, samplesPerPx: 110 });
      });
    });
  });
});
