import update from 'react-addons-update';
import { Matrix, Vector } from 'cal';
import * as actions from '../../../../actions/index.js';
import { addObjectActive2D, addObject, setActive2D } from '../../../objectReducers.js';
import createDebug from 'debug';
const debug = createDebug('d3d:reducer:circle');

const DEFAULT_RADIUS = 25;
const DEFAULT_SEGMENT = Math.PI * 0.5; // for segmented circle
const MAX_SEGMENT = Math.PI * 2;

export default function circleReducer(state, action, segmented = false) {
  if (action.log !== false) debug(action.type);
  const { position, screenMatrixZoom } = action;
  let scenePosition;
  if (position !== undefined && screenMatrixZoom !== undefined) {
    scenePosition = position.applyMatrix(screenMatrixZoom.inverseMatrix());
  }
  const activeShape = state.d2.activeShape;
  switch (action.type) {
    case actions.D2_DRAG_START: {
      return addObjectActive2D(state, {
        type: (segmented ? 'CIRCLE_SEGMENT' : 'CIRCLE'),
        transform: new Matrix({ x: scenePosition.x, y: scenePosition.y })
      });
    }
    case actions.D2_DRAG: {
      if (activeShape) {
        const beginPos = new Vector().copy(state.objectsById[activeShape].transform);
        const delta = scenePosition.subtract(beginPos);
        let segment;
        if (segmented) {
          segment = (delta.angle() + Math.PI * 2.5) % MAX_SEGMENT;
        } else {
          segment = MAX_SEGMENT;
        }
        const radius = delta.length();
        state = updateCircle(state, activeShape, radius, segment);
      }
      return state;
    }
    case actions.D2_DRAG_END: {
      if (activeShape) {
        state = setActive2D(state, null);
      }
      return state;
    }
    case actions.D2_TAP: {
      const segment = segmented ? DEFAULT_SEGMENT : MAX_SEGMENT;

      return addObject(state, {
        type: (segmented ? 'CIRCLE_SEGMENT' : 'CIRCLE'),
        transform: new Matrix({ x: scenePosition.x, y: scenePosition.y }),
        circle: {
          radius: DEFAULT_RADIUS,
          segment
        }
      });
    }
    default:
      return state;
  }
}
function updateCircle(state, id, radius, segment) {
  return update(state, {
    objectsById: {
      [id]: {
        circle: {
          radius: { $set: radius },
          segment: { $set: segment }
        }
      }
    }
  });
}
