/* dIntProg Browser. A webbrowser written in Java.
 * Copyright (C) 2001 Martin Geisler <gimpster@gimpster.com>
 *  
 * 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 2 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, write to the
 * 
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

import java.net.*;

/** This class represents the state of the browser. That includes the
    current URL, the home URL, stacks of URLs used to go forward and
    backward, and the location of links in the current document. */
public class BrowserModel {

    private URL current_url, home_url;
    private Stack forward_stack = new Stack();
    private Stack backward_stack = new Stack();
    private Set seen_URLs = new Set();
    private HyperLinkSet current_links = new HyperLinkSet();

    /** Constructs a new <code>BrowserModel</code>.
     *  @param u the new home URL. */
    public BrowserModel(URL u) {
        home_url = u;
    }

    /** Inserts a {@ling HyperLink} in the list of current links.
     *  @param l the new {@link HyperLink}. */
    public void registreLink(HyperLink l) {
        current_links.insert(l);
    }

    /** Reports if the URL in <code>l</code> has been seen before.
     *  @param l the {@link HyperLink} to check for.
     *  @return true if the URL has been seen before, false otherwise.
     *  */
    public boolean seenLink(HyperLink l) {
        return seen_URLs.member(l.getURL());
    }
            

    /** Returns the current URL.
     * @return the current URL. */
    public URL getCurrentURL() {
        return current_url;
    }
    
    /** Returns the home URL.
     * @return the home URL. */
    public URL getHomeURL() {
        return home_url;
    }

    /** Returns the URL that should be used if the user want's to go forward.
     * @return an URL if the forward-stack is not empty,
     * <code>null</code> otherwise. */
    public URL getForwardURL() {
        return (URL)forward_stack.peek();
    }

    /** Returns the URL that should be used if the user want's to go backward.
     * @return an URL if the backward-stack is not empty,
     * <code>null</code> otherwise. */
    public URL getBackwardURL() {
        return (URL)backward_stack.peek();
    }

    /** Returns the URL at (<code>x</code>, <code>y</code>). 
     *  @param x the <code>x</code> coordinate.
     *  @param y the <code>y</code> coordinate.
     *  @return the URL at (<code>x</code>, <code>y</code>) or
     *  <code>null</code> if there wasn't any URL at that point. */
    public URL getURL(int x, int y) {
        return current_links.getURL(x, y);
    }

    /** Updates the current URL.
     *  @param url the new current URL. */
    private void updateCurrentURL(URL url) {
        current_url = url;
        current_links.clear();
        seen_URLs.add(url);
    }

    /** Goes to a new URL. The current URL is pushed onto the
     * back-stack and the forward-stack is cleared, as it's no longer
     * possible to go forward from this point.
     * @param u the new URL. If it's <code>null</code>, then no action
     * is taken.
     * @return the new URL (the same as <code>u</code>). */
    public URL goToNewURL(URL u) {
        if (u != null) {
            forward_stack.clear();
            backward_stack.push(current_url);
            updateCurrentURL(u);
            return current_url;
        } else {
            return null;
        }
    }

    /** Goes home.
     * @return the home URL. */
    public URL goHome() {
        return goToNewURL(home_url);
    }

    /** Goes forward.
     * @return the new current URL, or <code>null</code> if it wasn't
     * possible to go forward. */
    public URL goForward() {
        if (forward_stack.empty()) {
            return null;
        } else {
            backward_stack.push(current_url);
            updateCurrentURL((URL)forward_stack.pop());
            return current_url;
        }
    }

    /** Goes backward.
     * @return the new current URL, or <code>null</code> if it wasn't
     * possible to go backward. */
    public URL goBackward() {
        if (backward_stack.empty()) {
            return null;
        } else {
            forward_stack.push(current_url);
            updateCurrentURL((URL)backward_stack.pop());
            return current_url;
        }
    }

}