/**
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.openstreetmap.josm.plugins.followline;

import static org.openstreetmap.josm.tools.I18n.tr;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.actions.mapmode.DrawAction;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.tools.Shortcut;

class FollowLineMenuAction extends JosmAction {

	public FollowLineMenuAction() {
		super(
				tr("Follow line"),
				"followline.png",
				tr("Continues drawing a line that shares nodes with another line."),
				Shortcut.registerShortcut("tools:followline", tr(
						"Tool: {0}", tr("Follow")),
						KeyEvent.VK_F, Shortcut.GROUP_MENU), false);
	}

	@Override
	protected void updateEnabledState() {
		if (getCurrentDataSet() == null) {
			setEnabled(false);
		} else {
			updateEnabledState(getCurrentDataSet().getSelected());
		}
	}

	@Override
	protected void updateEnabledState(
			Collection<? extends OsmPrimitive> selection) {
		setEnabled(selection != null && !selection.isEmpty());
	}

	@Override
	public void actionPerformed(ActionEvent evt) {
		OsmDataLayer osmLayer = Main.main.getEditLayer();
		if (osmLayer == null) return;
		if (Main.map.mapMode.getClass().getName() != DrawAction.class.getName()) return; // We are not on draw mode
		Collection<Node> selectedPoints = osmLayer.data.getSelectedNodes();
		Collection<Way> selectedLines = osmLayer.data.getSelectedWays();
		if ((selectedPoints.size() > 1) || (selectedLines.size() != 1)) return; // Unsuitable selection
		Node last = ((DrawAction) Main.map.mapMode).getCurrentBaseNode();
		Way follower = selectedLines.iterator().next();
		Node prev = follower.getNode(1);
		boolean reversed = true;
		if (follower.lastNode().equals(last)) {
			prev = follower.getNode(follower.getNodesCount() - 2);
			reversed = false;
		}
		List<OsmPrimitive> referrers = last.getReferrers();
		if (referrers.size() < 2) return; // There's nothing to follow
		Iterator<OsmPrimitive> i = referrers.iterator();
		while (i.hasNext()) {
			OsmPrimitive referrer = i.next();
			if (!referrer.getType().equals(OsmPrimitiveType.WAY)) continue; // Can't follow points or relations
			Way toFollow = (Way) referrer;
			if (toFollow.equals(follower)) continue;
			List<Node> points = toFollow.getNodes();
			int indexOfLast = points.indexOf(last);
			int indexOfPrev = points.indexOf(prev);
			if ((indexOfLast == -1) || (indexOfPrev == -1)) continue; // Both points must belong to both lines
			if (Math.abs(indexOfPrev - indexOfLast) != 1) continue; // ...and be consecutive
			Node newPoint = null;
			if (indexOfPrev == (indexOfLast - 1)) {
				if ((indexOfLast + 1) < points.size()) {
					newPoint = points.get(indexOfLast + 1);
				}
			}
			else {
				if ((indexOfLast - 1) >= 0) {
					newPoint = points.get(indexOfLast - 1);
				}
			}
			if (newPoint != null) {
				if (reversed)
					follower.addNode(0, newPoint);
				else
					follower.addNode(newPoint);
				osmLayer.data.clearSelection();
				osmLayer.data.addSelected(follower);
				osmLayer.data.addSelected(newPoint);
				return;
			}
		}
	}
}
