/**
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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.
 */
package org.jboss.webbeans.environment.se.example.roadmapmodel;

import java.util.HashSet;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.event.Event;
import javax.event.Fires;
import javax.inject.Initializer;

/**
 * represents a road on the road map. Each road may have a number of
 * {@link Intersection}s where it intersects with other roads.
 * @author Peter Royle
 */
public class Road
{

    private Orientation orientation;
    private int offset;
    private int start;
    private int end;
    private int length;
    private Set<Intersection> intersections = new HashSet<Intersection>();
    private int x1;
    private int y1;
    private int x2;
    private int y2;
    @Fires
    @Created
    Event<RoadEvent> roadCreatedEvent;

//    Log log = Logging.getLog( Road.class );

//    public Road(  )
//    {
//        log.trace( "creating road" );
//    }
    /**
     * Creates a new road, setting the given values and calculating the 'end'
     * property.
     * @param orientation The horizontal/vertical orientation of the road.
     * @param offset One element of the coordinate of the starting point of the
     * road. For VERTICAL orientation, this is an X coordinate, otherwise it is
     * a Y coordinate.
     * @param start One element of the coordinate of the starting point of the
     * road. For VERTICAL orientation, this is an Y coordinate, otherwise it is
     * a X coordinate.
     * @param length The length of the road.
     */
    @Initializer
    public Road( @HackyRandom int offset, @HackyRandom int start, @HackyRandom int length )
    {
//        log.trace( "creating a road" );
        this.orientation = (Math.random() > 0.5) ? Orientation.HORIZONTAL : Orientation.VERTICAL;
        this.offset = offset;
        this.start = start;
        this.setLength( length );

        if (this.orientation.equals( Orientation.HORIZONTAL ))
        {
            this.x1 = this.start;
            this.y1 = this.offset;
            this.x2 = this.end;
            this.y2 = this.offset;
        } else
        {
            this.x1 = this.offset;
            this.y1 = this.start;
            this.x2 = this.offset;
            this.y2 = this.end;
        }
    }

    public Road( Orientation orientation, int offset, int start, int length )
    {
        this.orientation = orientation;
        this.offset = offset;
        this.start = start;
        this.length = length;
    }


    /**
     *
     * @return the co-ordinate of the end of this road.
     */
    public int getEnd()
    {
        return end;
    }

    /**
     * Sets the value for the end coordinate of this road. Will also set the
     * value for length base on the existing start position (which must always
     * exist).
     * @param end The co-ordinate to be set as the end for this road.
     * @todo fire an update event
     */

//    public void setEnd( int end )
//    {
//        this.end = end;
//        this.length = this.end - this.start;
//    }
    /**
     *
     * @return the set of intersections for this road.
     */
    public Set<Intersection> getIntersections()
    {
        return intersections;
    }

    /**
     *
     * @return the length of this road.
     */
    public int getLength()
    {
        return length;
    }

    /**
     * Sets the length of this road. also sets the end coordinate based on the
     * existing start coordinate which must always exist.
     * @param length the new length of this road.
     * @todo fire an update event
     */
    private void setLength( int length )
    {
        this.length = length;
        this.end = this.start + this.length;
    }

    /**
     * Return the horizontal/vertical offset of this road.
     * @return
     */
    public int getOffset()
    {
        return offset;
    }

    /**
     * Set the offset of this road.
     * @param offset The new offset for this road.
     * @todo fire an update event
     */

//    public void setOffset( int offset )
//    {
//        this.offset = offset;
//    }
    /**
     *
     * @return the orientation of this road.
     */
    public Orientation getOrientation()
    {
        return orientation;
    }

    /**
     *
     * @return the start coordinate of this road.
     */
    public int getStart()
    {
        return start;
    }

    public int getX1()
    {
        return x1;
    }

    public int getX2()
    {
        return x2;
    }

    public int getY1()
    {
        return y1;
    }

    public int getY2()
    {
        return y2;
    }

    @PostConstruct
    public void fireInitEvent()
    {
        roadCreatedEvent.fire( new RoadEvent( this ) );
    }

    public String toString()
    {
        return this.hashCode() + ": " + this.orientation + " road (" + this.offset + ", " + this.end + ")";
    }
}
