
/*
 * 
 *   Copyright 2016 RIFT.IO Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
/**
 * Created by onvelocity on 9/1/15.
 */

import Position from './Position'

const angleOfLine = function (x1, y1, x2, y2) {

	const y = y2 - y1;
	const x = x2 - x1;

	const rad = Math.atan2(y, x);
	const deg = Math.abs(rad * 180 / Math.PI);

	let addDeg = 0;

	if (rad <= 0) {
		addDeg = 360;
	}

	// - addDeg bc atan2 returns -π to π where -π is the upper side of rectangle
	// - 360 bc our ui grid system has zero in upper left corner not lower left
	return Math.abs(Math.abs(deg - addDeg) - 360);

};

const angleBetweenPositions = function (src, dst) {
	if (!src instanceof Position) {
		throw new ReferenceError('require a position instance');
	}
	if (!dst instanceof Position) {
		throw new ReferenceError('require a position instance');
	}
	const srcCenter = src.centerPoint();
	const dstCenter = dst.centerPoint();
	return angleOfLine(srcCenter.x, srcCenter.y, dstCenter.x, dstCenter.y);
};

const distanceBetweenPositions = function (src, dst) {
	if (!src instanceof Position) {
		throw new ReferenceError('require a position instance');
	}
	if (!dst instanceof Position) {
		throw new ReferenceError('require a position instance');
	}
	const srcCenter = src.centerPoint();
	const dstCenter = dst.centerPoint();
	const x = Math.pow(dstCenter.x - srcCenter.x, 2);
	const y = Math.pow(dstCenter.y - srcCenter.y, 2);
	const distance = Math.sqrt((x) + (y));
	if (isNaN(distance)) {
		console.log('nan distance', srcCenter, dstCenter);
	}
	return distance;
};

const rectangleAnglesFromCenter = function (position) {
	/* given a rectangle defined by a Position, determine the angle of each corner from center.
	 // note: 0˚ is on x-axis; angles are given counterclockwise from x-axis
	 // for example:
	 // the line AB(0, 0, 5, 0) would have angle 0˚
	 // the line AC(0, 0, 0, 5) would have angle 90˚
	 // the line BC(5, 0, 0, 5) would have angle 135˚
	 // the line BA(5, 0, 0, 0) would have angle 180˚
	 */
	if (!position instanceof Position) {
		throw new ReferenceError('require a Position instance');
	}
	const center = position.centerPoint();
	return [
		angleOfLine(center.x, center.y, position.right, position.top),
		angleOfLine(center.x, center.y, position.left, position.top),
		angleOfLine(center.x, center.y, position.left, position.bottom),
		angleOfLine(center.x, center.y, position.right, position.bottom)
	];
};

const edgeLocation = function (rectangleInclinations) {
	/* given the angle of a line, determine which edge of the rectangle the line should attach. */
	let inclinations = rectangleInclinations;
	if (rectangleInclinations instanceof Position) {
		inclinations = rectangleAnglesFromCenter(rectangleInclinations);
	}
	return angle => {
		angle = parseFloat(angle);
		if (angle >= inclinations[3]) {
			return 'right';
		}
		if (angle >= 270) {
			return 'bottom-right';
		}
		if (angle >= inclinations[2]) {
			return 'bottom-left';
		}
		if (angle >= inclinations[1]) {
			return 'left';
		}
		if (angle >= 90) {
			return 'top-left';
		}
		if (angle >= inclinations[0]) {
			return 'top-right';
		}
		return 'right';
	};
};

const upperLowerEdgeLocation = function (angle) {
	angle = parseFloat(angle);
	if (angle > 270) {
		return 'bottom-right';
	}
	if (angle > 180) {
		return 'bottom-left';
	}
	if (angle > 90) {
		return 'top-left';
	}
	return 'top-right';
};

export default {
	angleOfLine: angleOfLine,
	angleBetweenPositions: angleBetweenPositions,
	distanceBetweenPositions: distanceBetweenPositions,
	anglesFromCenter: rectangleAnglesFromCenter,
	edgeLocation: edgeLocation,
	upperLowerEdgeLocation: upperLowerEdgeLocation
}
