//script.coordinateSystem = 'bottom-up';
print(script.coordinateSystem);
script.angleUnits = 'radians';

if(scriptographer.version <= parseFloat(2.7)) {
	Dialog.alert('Roads only works on versions of Scriptographer higher then 2.7. Please upgrade Scriptographer first.');
} else {
	var values = {
		roadSize: 10,
		maxSpeed: 5,
		minSpeed: 0,
		count: 0,
		steering: 1.5
	}

	var components = {
		roadSize: {
			label: 'Size',
			range: [0, 100],
			steppers: true
		},

		maxSpeed: {
			label: 'Max Speed',
			range: [0, 50],
			steppers: true
		},

		steering: {
			label: 'Steering',
			range: [1, 2],
			type: 'slider',
			width: 100
		},

		help: {
			type: 'button',
			value: 'Instructions',
			onClick: function() {
				if(this.value == 'Instructions') {
					this.value = 'Close Instructions';
					components.instructions.value = '\n- Click and Drag to create a Road\n' +
													'- Steer it with Left and Right arrow keys\n' +
													'- Up to accelerate, Down to brake\n' + 
													'- Ctrl for handbrake\n' +
													'- Hold down Shift to make Road go under other roads\n' +
													'- Shift, Click and Drag to create multiple roads';
					components.instructions.height = null;
				} else {
					this.value = 'Instructions';
					components.instructions.value = '';
					components.instructions.height = 0;
				}
			}
		},

		instructions: {
			type: 'text',
			multiline: true,
			fullSize: true,
			value: '',
			height: 0
		}
	}

	var palette = new Palette('Roads', components, values);

	// var roadGroup = document.activeLayer.children['roads'];
	// if(!roadGroup) {
	// 	roadGroup = new Group();
	// 	roadGroup.name = 'roads';
	// }

	Road = Base.extend({
		initialize: function(position, rotation) {
			this.vector = new Point(1, 1);
			this.vector.angle = rotation;
			this.position = position;
			this.maxSteer = (4.5).toRadians();
			this.speed = 0;
			this.friction = 0.98;
			this.roadSize = values.roadSize;
			this.group = Road.getGroup();
			this.createPaths();
			this.draw();
			this.shiftDown = false;
			this.id = values.count;
			values.count++;
		},

		createPaths: function() {
			if(this.leftLine && this.leftLine.isValid()) {
				if(this.leftLine.isAbove(this.group)) {
					this.group.appendTop(this.leftLine.parent);
				} else {
					this.group.appendBottom(this.leftLine.parent);
				}
			}
			this.background = new Path() {
				strokeColor: null,
				fillColor: '#FFFFFF',
				name: 'background'
			};
			this.rightLine = new Path();
			this.rightLine.name = 'rightLine';
			this.leftLine = new Path();
			this.leftLine.name = 'leftLine';
			this.rightLine.style = this.leftLine.style = {
				strokeColor: 'black',
				fillColor: null,
				dashArray: null,
				strokeWidth: this.roadSize / 5,
				strokeCap: 'round'
			};

			var dashOffset = 0;
			if(this.centerLine)
				dashOffset = (this.centerLine.dashOffset + this.centerLine.length);
			this.centerLine = new Path() {
				dashArray: [this.roadSize / 2, this.roadSize * 0.8],
				dashOffset: dashOffset,
				fillColor: null,
				strokeColor: 'black',
				strokeWidth: this.roadSize / 10,
				name: 'centerLine',
				strokeCap: 'round'
			};
			var group = new Group([this.rightLine, this.leftLine, this.centerLine, this.background]);
			group.name = 'section';

			if(Key.isDown('shift')) {
				group.moveBelow(this.group);
			} else {
				group.moveAbove(this.group);
			}
			if(this.lastLeft) {
				this.leftLine.add(this.lastLeft);
				this.rightLine.add(this.lastRight);
				this.background.add(this.lastRight);
				this.background.add(this.lastLeft);
				this.centerLine.add(this.lastPosition);
			}
		},

		needsSplit: function() {
			return this.centerLine.segments.length > 30;
		},

		isValid: function() {
			return this.background.isValid();
		},

		remove: function() {
			roads.slice(this.id, 1);
		},

		left: function() {
			if(this.speed >= 0.01) {
				if (this.speed < 3 && this.speed >= 0) {
					this.vector.angle += (this.speed * 2).toRadians();
				} else if (this.speed < 0) {
					this.vector.angle += (this.speed / 2).toRadians();
				} else {
					this.vector.angle += this.maxSteer * values.steering;
				}
				this.speed *= this.friction;
			}
		},

		right: function() {
			if(this.speed >= 0.01) {
				if (this.speed < 3 && this.speed >= 0) {
					this.vector.angle -= (this.speed * 2).toRadians();
				} else if (this.speed < 0) {
					this.vector.angle -= (this.speed / 2).toRadians();
				} else {
					this.vector.angle -= this.maxSteer * values.steering;
				}
				this.speed *= this.friction;
			}
		},

		forward: function() {
			this.speed += 0.3;
			this.speed = Math.min(values.maxSpeed, this.speed);
		},

		reverse: function() {
			this.speed -= 0.3;
			if(this.speed < values.minSpeed)
				this.speed = values.minSpeed;
		},

		handbrake: function() {
			this.speed -= this.speed / 10;
			if (Key.isDown('right')) {
		 		this.vector.angle -= (this.speed / 2).toRadians();
			}
			if (Key.isDown('left')) {
			    this.vector.angle += (this.speed / 2).toRadians();
			}
		},

		draw: function() {
			if(this.isValid()) {
				var vec = this.vector.clone();
				vec.length = Math.abs(this.speed);
				this.speed = this.speed * this.friction;
				if(this.speed < 0) {
					this.position -= vec;
				} else {
					this.position += vec;
				}

				vec.angle += (90).toRadians();
				vec.length = this.roadSize;

				var left = this.position + vec;
				var right = this.position - vec;

				if(this.lastLeft) {
					var hitResult = this.background.hitTest(left, 0.001) || this.background.hitTest(right, 0.001);
					if(this.speed > 1 && hitResult) {
						this.createPaths();
					}
				}

				if(Math.abs(this.speed) > 0) {
					if(this.lastVector && this.leftLine.segments.length > 2 && this.lastVector.angle == this.vector.angle) {
						this.leftLine.segments.last.point = left;
						this.rightLine.segments.last.point = right;
						this.background.segments.last.point = left;
						this.background.segments.first.point = right;
						this.centerLine.segments.last.point = this.position;
					} else {
						this.leftLine.add(left);
						this.rightLine.add(right);
						this.background.add(left);
						this.background.insert(0, right);
						this.centerLine.add(this.position);
					}
					this.lastLeft = left;
					this.lastRight = right;
				}
				this.lastVector = this.vector.clone();
				this.lastPosition = this.position.clone();
			} else {
				var index;
				for(var i = 0; i < roads.length; i++) {
					if(roads[i].id == this.id)
						index = i;
				}
				roads.splice(index, 1);
				for(var i = 0; i < roads.length; i++) {
					var road = roads[i];
					if(road.id > this.id)
						road.id = road.id - 1;
				}
			}
		},

		statics: {
			getGroup: function() {
				if(document && (!this.roadGroup || !this.roadGroup.isValid())) {
					var roadGroup = document.activeLayer.children['roads'];
					if(roadGroup && roadGroup.isValid()) {
						this.roadGroup = roadGroup;
					} else {
						this.roadGroup = new Group();
						this.roadGroup.name = 'roads';
					}
				}
				return this.roadGroup
			},

			cleanUp: function() {
				var roadGroup = document.activeLayer.children['roads'];
				if(roadGroup) {
					var items = document.activeLayer.children;
					for(var i = 0; i < items.length; i++) {
						var item = items[i];
						if(item.name == 'section') {
							if(item.isAbove(roadGroup)) {
								roadGroup.appendTop(item);
							} else {
								roadGroup.appendBottom(item);
							}
						}
					}
				}
			}
		}
	});

	var roads = [];

	// move any existing road sections that aren't in the roads group
	// into the roads group:
	if(document)
		Road.cleanUp();

	function onMouseUp(event) {
		if(!Key.isDown('shift') && roads.length)
			roads.pop();
		var road = new Road(event.point, event.delta.angle);
		road.speed = event.delta.length / 20;
		if(road.speed < 0.05)
			road.speed = 0.05;
		road.draw();
		roads.push(road);
	}

	var shiftDown = false;

	function moveRoad() {
		for(var i = 0; i < roads.length; i++) {
			var road = roads[i];
			road.group = Road.getGroup();
			if(Key.isDown('shift')) {
				if(!road.shiftDown) {
					if(!road.group.hitTest(road.lastLeft) &&
					   !road.group.hitTest(road.lastRight) &&
					   !road.group.hitTest(road.lastPosition)) {
						road.createPaths();
						road.shiftDown = true;
					}
				}
			} else {
				if(road.shiftDown || road.needsSplit()) {
					if(!road.group.hitTest(road.lastLeft) &&
					   !road.group.hitTest(road.lastRight) &&
					   !road.group.hitTest(road.lastPosition)) {
						road.createPaths();
						road.shiftDown = false;
					}
				}
			}

			if(Key.isDown('left'))
				road.left();

			if(Key.isDown('right'))
				road.right();

			if(Key.isDown('up'))
				road.forward();

			if(Key.isDown('down'))
				road.reverse();

			if(Key.isDown('control'))
				road.handbrake();
			road.draw();
		}
	}

	var movingRoad = setInterval(moveRoad, 30);
}