import curry from 'lodash/curry';
import flow from 'lodash/flow';
import isNumber from 'lodash/isNumber';
import { throwInDev, throwTypeError } from '../throwInDev';
import { PositionRecord } from '../../constants/flowdesigner.model';
import { PositionRecord as PositionRecordType } from '../../customTypings/index.d';
/**
* @desc Represent a position comprised of X and Y coordinates
* avoid reading directly, use the Size module api
* Do not mutate it manually, use the Size module api
* @example
Create a Position
* const position = Position.create(100, 200);
* @example Read from Position
* const x = Size.getXCoordinate(position);
* @example transform a Position
* const position = Size.setXCoordinate(100, position);
* @typedef {Immutable.Record} PositionRecord
*/
/**
* given a parameter check if it is a PositionRecord
* @param {*} position
* @return {bool}
*/
export function isPosition(position: PositionRecordType) {
if (position && position instanceof PositionRecord) {
return true;
}
return false;
}
/**
* given a parameter check if it is a PositionRecord, if not throw in developpement
* @param {*} position
* @return {bool}
*/
export function isPositionElseThrow(position: PositionRecordType) {
const test = isPosition(position);
if (!test) {
throwTypeError('PositionRecord', position, 'Position');
}
return test;
}
/**
* given a PositionRecord return X coordinate
* @param {PositionRecord} position
* @return {number}
*/
export function getXCoordinate(position: PositionRecordType) {
if (isPositionElseThrow(position)) {
return position.get('x');
}
return null;
}
/**
* given a number and a PositionRecord return updated PositionRecord
* @function
* @param {number} x
* @param {PositionRecord} position
* @return {PositionRecord}
*/
export const setXCoordinate = curry((x: number, position: PositionRecordType) => {
if (isPositionElseThrow(position) && isNumber(x)) {
return position.set('x', x);
}
throwInDev(`x should be a number, was given ${x && x.toString()} of type ${typeof x}`);
return position;
});
/**
* given a PositionRecord return the Y coordinate
* @param {PositionRecord} position
* @return {number}
*/
export function getYCoordinate(position: PositionRecordType) {
if (isPositionElseThrow(position)) {
return position.get('y');
}
return null;
}
/**
* given a number and a PositionRecord return updated PositionRecord
* @param {number} y
* @param {PositionRecord} position
* @return {PositionRecord}
*/
export const setYCoordinate = curry((y: number, position: PositionRecordType) => {
if (isPositionElseThrow(position) && isNumber(y)) {
return position.set('y', y);
}
throwInDev(`y should be a number, was given ${y && y.toString()} of type ${typeof y}`);
return position;
});
/**
* given x and y coordinate return a PositionRecord
* @param {number} x
* @param {number} y
* @return {PositionRecord}
*/
export const create = curry((x: number, y: number) =>
flow([setXCoordinate(x), setYCoordinate(y)])(new PositionRecord()),
);