import { TimelineState } from '../../types';

const round = (x: number, digits: number = 8) => Math.round(x * Math.pow(10, digits)) / Math.pow(10, digits);

export const pxToSamples = (state: TimelineState, px: number) => px * state.samplesPerPx;
export const samplesToPx = (state: TimelineState, samples: number) => samples / state.samplesPerPx;

export const viewportPxToSamples = (state: TimelineState, px: number) => pxToSamples(state, px + state.scrollLeft - state.padding);
export const samplesToViewportPx = (state: TimelineState, samples: number) => samplesToPx(state, samples) + state.padding - state.scrollLeft;

export const getContentWidth = (state: TimelineState) => samplesToPx(state, state.duration) + (2 * state.padding);

export const getFocusWidth = (state: TimelineState) => state.viewportWidth - (2 * state.padding);

export const clampScrollLeft = (state: TimelineState, targetScrollLeft: number) => Math.max(
  0,
  Math.min(
    targetScrollLeft,
    getContentWidth(state) - state.viewportWidth
  )
);

export const scroll = (state: TimelineState, scrollAmount: number): TimelineState => ({
  ...state,
  scrollLeft: clampScrollLeft(state, state.scrollLeft + scrollAmount)
});

export const setScroll = (state: TimelineState, targetScrollLeft: number): TimelineState => ({
  ...state,
  scrollLeft: clampScrollLeft(state, targetScrollLeft)
});

/** express start and end in samples */
export const showBounds = (state: TimelineState, start: number, end: number): TimelineState => {
  const duration = end - start;
  const samplesPerPx = round(duration / getFocusWidth(state));
  const targetScrollLeft = start / samplesPerPx;
  return {
    ...state,
    samplesPerPx,
    scrollLeft: clampScrollLeft({...state, samplesPerPx}, targetScrollLeft)
  }
}

/** express point in samples */
export const showPoint = (state: TimelineState, point: number): TimelineState => {
  const scrollLeft = clampScrollLeft(state, samplesToPx(state, point) - getFocusWidth(state) / 2);
  if (scrollLeft === state.scrollLeft) {
    return state;
  }
  return {
    ...state,
    scrollLeft
  }
}

export const scaleByFactor = (state: TimelineState, factor: number): TimelineState => {
  const midPoint = viewportPxToSamples(state, state.viewportWidth / 2);
  const samplesPerPx = round(state.samplesPerPx / factor);
  return showPoint({ ...state, samplesPerPx }, midPoint);
};
