/* 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.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.*;
import java.awt.Cursor;
import javax.swing.*;
import java.net.*;

/** The controller of the browser. This class is responsible for
 *  reacting on the events that are generated when the user clicks the
 *  buttons or move the mouse. The controller uses a {@link
 *  BrowserModel} to handle the logic associated with navigating
 *  forward and backward. A {@link DocumentView} is created as needed
 *  to display the {@link DocumentModel} returned by the {@link
 *  Parser}. */
public class BrowserController
    extends JFrame
    implements ActionListener, MouseListener, MouseMotionListener {

    private JScrollPane scroll_pane;
    private JLabel status;
    private JTextField url_field;
    private JButton forward, backward, home, go;

    private DocumentView view;
    private BrowserModel model;

    public BrowserController(URL url) {
        Browser.debug("BrowserController created.");
        
        model = new BrowserModel(url);

	JPanel top_top = new JPanel(new FlowLayout());
	JPanel top_bot = new JPanel(new FlowLayout());

	url_field = new JTextField(30);
	go = new JButton("Go!");
        go.addActionListener(this);
	top_top.add(new JLabel("Url:"));
	top_top.add(url_field);
	top_top.add(go);
	
	forward = new JButton("Forward");
        forward.addActionListener(this);
	backward = new JButton("Back");
        backward.addActionListener(this);
	home = new JButton("Home");
        home.addActionListener(this);
	top_bot.add(forward);
	top_bot.add(backward);
	top_bot.add(home);

	JPanel top_panel = new JPanel(new GridLayout(2, 1));
	top_panel.add(top_top);
	top_panel.add(top_bot);

	Container c = getContentPane();
	c.setLayout(new BorderLayout());
	c.add(top_panel, BorderLayout.NORTH);

	scroll_pane = new JScrollPane();
	c.add(scroll_pane, BorderLayout.CENTER);

	status = new JLabel("Status:");
	c.add(status, BorderLayout.SOUTH);

        /* Create a view and insert it into the scrollpane. */
	newURL(model.goToNewURL(url));

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	setSize(480, 640);
	setTitle("dIntProg Browser");
	setVisible(true);
    }

    /** Returns a string representation of an URL.
     *  @return the commonly used 'protocol://host/path' string. */
    private String URLToString(URL url) {
        return url.getProtocol() + "://" + url.getHost() + url.getPath();
    }
    
    /** Switched to a new URL. The URL is given to the {@link Parser}
     *  which produces a {@link DocumentModel}. The model is then used
     *  in the construction of a new {@link DocumentView}, which is
     *  inserted into the scrollpane.
     *  @param url the new URL. It is allowed to be <code>null</code>.
     *  */
    private void newURL(URL url) {
        if (url != null) {
            view = new DocumentView(Parser.parse(url), model);
            view.addMouseListener(this);
            view.addMouseMotionListener(this);
            
            scroll_pane.setViewportView(view);
            url_field.setText(URLToString(url));
            if (view.getTitle().equals("")) {
                setTitle(URLToString(url) + " - dIntProg Browser");
            } else {
                setTitle(view.getTitle() + " - dIntProg Browser");
            }
        }
    }

    /** The eventhandler for button clicks. The source of the event is
     *  tested agains the variuos buttons, and the appropriate action
     *  is taken.
     *  @param e the event. */
    public void actionPerformed(ActionEvent e) {
        Object sender = e.getSource();
	if (sender == home) {
            newURL(model.goHome());
        } else if (sender == go) {
	    try {
                newURL(model.goToNewURL(new URL(url_field.getText())));
	    } catch (MalformedURLException x) {
		Browser.debug("Malformaed URL");
	    }
	} else if (sender == forward) {
            newURL(model.goForward());
        } else if (sender == backward) {
            newURL(model.goBackward());
        }
    }
    
    /** The eventhandler for mouseclicks. The {@link BrowserModel} is
     *  queried to see if there's a link at the point where the mouse
     *  was pressed. If so, the link will be followed.
     *  @param e the event.*/
    public void mouseClicked(MouseEvent e) {
        newURL(model.goToNewURL(model.getURL(e.getX(), e.getY())));
    }
    
    /** Updates the status field when the mouse moves. When the mouse
     *  moves over a link, the cursor is changed into a hand.
     *  @param e the event. */
    public void mouseMoved(MouseEvent e) {
        URL url = model.getURL(e.getX(), e.getY());
        if (url != null) {
            status.setText("Link: " + URLToString(url));
            setCursor(Cursor.HAND_CURSOR);
        } else {
            status.setText("Link: (none)");
            setCursor(Cursor.DEFAULT_CURSOR);
        }
    }

    /** Dummy eventhandler. Does nothing.
     *  @param e the event - it will be discarded. */
    public void mouseEntered(MouseEvent e) {}

    /** Dummy eventhandler. Does nothing.
     *  @param e the event - it will be discarded. */
    public void mouseExited(MouseEvent e) {}

    /** Dummy eventhandler. Does nothing.
     *  @param e the event - it will be discarded. */
    public void mousePressed(MouseEvent e) {}

    /** Dummy eventhandler. Does nothing.
     *  @param e the event - it will be discarded. */
    public void mouseReleased(MouseEvent e) {}

    /** Dummy eventhandler. Does nothing.
     *  @param e the event - it will be discarded. */
    public void mouseDragged(MouseEvent e) {}

}