/* WorkspaceLoader.java
 * =========================================================================
 * This file is part of the GrInvIn project - http://www.grinvin.org
 * 
 * Copyright (C) 2005-2008 Universiteit Gent
 * 
 * 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.
 * 
 * A copy of the GNU General Public License can be found in the file
 * LICENSE.txt provided with the source distribution of this program (see
 * the META-INF directory in the source jar). This license can also be
 * found on the GNU website at http://www.gnu.org/licenses/gpl.html.
 * 
 * If you did not receive a copy of the GNU General Public License along
 * with this program, contact the lead developer, or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package org.grinvin.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipInputStream;

import org.grinvin.workspace.WindowSubsystem;
import org.grinvin.workspace.Workspace;
import org.grinvin.workspace.WorkspaceException;

import org.jdom.Element;
import org.jdom.JDOMException;

/**
 * Loads workspaces from disk.
 */
public class WorkspaceLoader {
    
    //
    private static final Logger LOGGER
            = Logger.getLogger("org.grinvin.workspace", "org.grinvin.workspace.resources");

    //
    private Workspace workspace;
    
    //
    private SectionLoader sloader;
    
    // meta-information stored in the file
    private Properties meta;
    
    private WorkspaceLoader(Workspace workspace, SectionLoader sloader) {
        this.workspace = workspace;
        this.sloader = sloader;
    }
    
    /**
     * Load the meta-information for the workspace.
     */
    private void loadMeta() throws IOException {
        meta = new Properties();
        InputStream in = sloader.openSection("meta-info.xml");
        if (in != null) {
            meta.loadFromXML(in);
            in.close();
        } else {
            // when meta-info does not exist, we have a grinvin-1.0 workspace
            meta.setProperty("version", "1.0");
        }
    }
    
    /**
     * Load the workspace from the given workspace file. If there
     * is an active workspace already, it is first saved and then disposed of.
     */
    private void load() throws IOException, JDOMException, WorkspaceException {
        if (workspace.getLocation() != null) {
            WorkspaceSaver.save(workspace);
            workspace.dispose();
        }
        
        loadMeta();
        if (meta.getProperty("version").equals("1.0")) {
            InputStream input = sloader.openSection("meta.xml");
            Element root = LoaderSaverHelper.loadElementNonValidating(input, "workspace");

            for (Subsystem subsystem : workspace.subsystems)
                if (subsystem instanceof WindowSubsystem)
                    ((WindowSubsystem)subsystem).load_1_0(root, sloader);
            
        } else {
            InputStream input = sloader.openSection("workspace.xml");
            Element root = LoaderSaverHelper.loadElement(input);

            // in order of registration
            for (Subsystem subsystem : workspace.subsystems)
                subsystem.load(root, sloader);
        }
    }

    /**
     * Load the workspace from the given workspace file. If there
     * is an active workspace already, it is first saved and then disposed of.
     */
    public static void load(Workspace workspace, File file) throws WorkspaceException {
        try {
            FileInputStream in = new FileInputStream(file);
            ZipInputStream zip = new ZipInputStream(in);
        
            WorkspaceLoader loader = new WorkspaceLoader(workspace, new ZipInputStreamSectionLoader(zip));
            loader.load();
            workspace.setLocation(file);
            LOGGER.log(Level.INFO, "log.loaded.workspace", file);
        } catch (IOException ex) {
            throw new WorkspaceException("I/O error while loading workspace",
                    file, ex);
        } catch (JDOMException ex) {
            throw new WorkspaceException("I/O format error in meta.xml",
                    file, ex);
        }
    }

    /**
     * Load the workspace from the given workspace directory. If there
     * is an active workspace already, it is first saved and then disposed of.
     */
    public static void loadFromDirectory(Workspace workspace, File directory) throws WorkspaceException {
        try {
            WorkspaceLoader loader = new WorkspaceLoader(workspace, new DirectorySectionLoader(directory));
            loader.load();
            workspace.setLocation(directory);
            LOGGER.log(Level.INFO, "log.loaded.workspace", directory);
        } catch (IOException ex) {
            throw new WorkspaceException("I/O error while loading workspace",
                    directory, ex);
        } catch (JDOMException ex) {
            throw new WorkspaceException("I/O format error in meta.xml",
                    directory, ex);
        }
    }

    
}
