package net.kenevans.dilbert.views;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import net.kenevans.dilbert.plugin.IPluginConstants;
import net.kenevans.dilbert.plugin.ImageActions;
import net.kenevans.dilbert.utils.Utils;
import net.kenevans.imagemodel.ImageModel;
import net.kenevans.imagemodel.ImagePanel;
import net.kenevans.jai.plugin.JAIPlugin;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * DilbertView. Creates a view with an ImagePanel.
 * 
 * @author Kenneth Evans, Jr.
 */
public class DilbertView extends ViewPart implements IPluginConstants
{
    public static final String ID = PLUGIN_ID + ".DilbertView";
    Composite awtComposite = null;
    private java.awt.Frame frame = null;
    private static ImagePanel imagePanel = null;
    private static ImageModel imageModel = null;
    private String result = "Error";
    private ImageActions imageActions = null;
    protected Action renewAction;
    protected Action infoAction;

    public DilbertView() {
        // // Logging needs to be set up to avoid warnings about no log4j
        // appenders
        // // found. Set the level of the root logger, otherwise you get ALL.
        // Logger logger = Logger.getRootLogger();
        // logger.setLevel(Level.WARN);
        // // Set logging to the console
        // BasicConfigurator.configure();

        // Insure that the JAI plug-in gets loaded before doing image things.
        // This
        // will not happen automatically since we do not explicitly call any of
        // its
        // methods.
        JAIPlugin.getDefault();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
     * .Composite)
     */
    @Override
    public void createPartControl(Composite parent) {
        // Make a Frame in a Composite
        awtComposite = new Composite(parent, SWT.EMBEDDED);
        frame = SWT_AWT.new_Frame(awtComposite);
        imageModel = new ImageModel();
        imagePanel = new ImagePanel(imageModel);
        imageActions = new ImageActions(imagePanel);
        frame.add(imagePanel);
        getNewDilbertImage();

        // Create the actions
        makeActions();
        contributeToActionBars();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        if(imageActions != null) {
            imageActions.setImagePanel(null);
            imageActions = null;
        }
        if(frame != null) {
            if(imagePanel != null) frame.remove(imagePanel);
            frame = null;
        }
        imagePanel = null;
        if(awtComposite != null && !awtComposite.isDisposed()) {
            awtComposite.dispose();
            awtComposite = null;
        }
        super.dispose();
    }

    /**
     * Gets a new image via the web service.
     */
    public void getNewDilbertImage() {
        BufferedImage image = null;
        try {
            // Get it from the Dilbert site
            URL url = new URL("http://www.dilbert.com");
            // Look for /dyn/str_strip/xxx.strip.gif
            String imageUrlString = null;

            String regex = "(/dyn/str_strip/.*\\.strip\\.gif)";
            Pattern pattern = Pattern.compile(regex);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                url.openStream()));
            String line;
            while((line = br.readLine()) != null) {
                Matcher matcher = pattern.matcher(line);
                if(matcher.find()) {
                    imageUrlString = "http://www.dilbert.com" + matcher.group();
                    // System.out.println(matcher.group());
                    // System.out.println(retVal);
                }
            }
            if(br != null) {
                br.close();
            }

            // May 2011: Seems to have the Sunday strip at strip.sunday.gif
            // Try this if the above fails
            if(imageUrlString == null) {
                regex = "(/dyn/str_strip/.*\\.strip\\.sunday\\.gif)";
                pattern = Pattern.compile(regex);
                br = new BufferedReader(new InputStreamReader(url.openStream()));
                while((line = br.readLine()) != null) {
                    Matcher matcher = pattern.matcher(line);
                    if(matcher.find()) {
                        imageUrlString = "http://www.dilbert.com"
                            + matcher.group();
                        // System.out.println(matcher.group());
                        // System.out.println(retVal);
                    }
                }
                if(br != null) {
                    br.close();
                }
            }

            // Set the image
            url = new URL(imageUrlString);
            image = ImageIO.read(url);
            imageModel.replaceImage(image);
            imagePanel.repaint();
        } catch(Exception ex) {
            Utils.excMsg("Getting image failed:", ex);
        }
    }

    /**
     * Shows the result obtained when getting the image.
     */
    public void showInfo() {
        String ls = Utils.LS;
        String info = "";
        info += result + ls;
        Utils.infoMsg(info);
    }

    /**
     * Creates view-related actions.
     */
    private void makeActions() {
        // Refresh view
        renewAction = new Action() {
            public void run() {
                getNewDilbertImage();
            }
        };
        renewAction.setText("Renew");
        renewAction.setToolTipText("Renew");
        renewAction.setImageDescriptor(AbstractUIPlugin
            .imageDescriptorFromPlugin(PLUGIN_ID, "icons/refresh.gif"));

        // Info
        infoAction = new Action() {
            public void run() {
                showInfo();
            }
        };
        infoAction.setText("Info");
        infoAction.setToolTipText("Info");
        infoAction.setImageDescriptor(PlatformUI.getWorkbench()
            .getSharedImages()
            .getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
    }

    /**
     * Contributes to the action bars. Subclasses must call this method in
     * createPartControl for them to appear. Subclasses should not override but
     * should implement fillLocalPullDown and fillLocalToolBar.
     */
    protected void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    /**
     * Fills the local pulldown menu on the View. Subclasses can override.
     * 
     * @param manager
     */
    protected void fillLocalPullDown(IMenuManager manager) {
        manager.add(renewAction);
        manager.add(infoAction);
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        manager.add(imageActions.fitAction);
        manager.add(imageActions.copyAction);
        manager.add(imageActions.saveAsAction);
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        manager.add(imageActions.pageSetupAction);
        manager.add(imageActions.printPreviewAction);
        manager.add(imageActions.printAction);
    }

    /**
     * Fills the local toolbar menu on the View. Subclasses can override.
     * 
     * @param manager
     */
    protected void fillLocalToolBar(IToolBarManager manager) {
        manager.add(renewAction);
        manager.add(infoAction);
    }

    /**
     * @return The value of the latest result from getting the image.
     */
    public String getResult() {
        return result;
    }

}
