/*
 * Copyright (C) 2016 Patrick Balleux (Twitter: @patrickballeux)
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 * This is an XML FORMAT to keep the settings for ScreenStudio
 * <screenstudio>
 * <webcam/>
 * <image/>
 * <label/>
 * <audio/>
 * <setting/>
 * <output/>
 * </screenstudio>
 */
package screenstudio.targets;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import screenstudio.encoder.FFMpeg;
import screenstudio.sources.effects.Effect;
import screenstudio.sources.transitions.Transition;

/**
 * @author patrick
 */
public class Layout {

    private Document document = null;
    private Node root = null;
    private Node output = null;
    private Node audios = null;
    private Node settings = null;

    public enum SourceType {
        Desktop, Webcam, Image, LabelText, Video, Stream, Frame, Custom
    }

    public Layout() {
        try {
            this.document = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            root = this.document.createElement("screenstudio");
            document.appendChild(root);
            audios = document.createElement("audios");
            root.appendChild(audios);
            output = document.createElement("output");
            root.appendChild(output);
            settings = document.createElement("settings");
            root.appendChild(settings);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Layout.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void setOutputWith(int value) {
        Node node = document.createAttribute("outputwidth");
        node.setNodeValue("" + value);
        output.getAttributes().setNamedItem(node);
    }

    public int getOutputWidth() {
        return new Integer(output.getAttributes().getNamedItem("outputwidth").getNodeValue());
    }

    public void setOutputHeight(int value) {
        Node node = document.createAttribute("outputheight");
        node.setNodeValue("" + value);
        output.getAttributes().setNamedItem(node);
    }

    public int getOutputHeight() {
        return new Integer(output.getAttributes().getNamedItem("outputheight").getNodeValue());
    }

    public void setOutputFramerate(int value) {
        Node node = document.createAttribute("outputframerate");
        node.setNodeValue("" + value);
        output.getAttributes().setNamedItem(node);

    }

    public int getOutputFramerate() {
        return new Integer(output.getAttributes().getNamedItem("outputframerate").getNodeValue());
    }

    public void setOutputTarget(FFMpeg.FORMATS value) {
        Node node = document.createAttribute("outputtarget");
        node.setNodeValue(value.name());
        output.getAttributes().setNamedItem(node);

    }

    public FFMpeg.FORMATS getOutputTarget() {
        return FFMpeg.FORMATS.valueOf(output.getAttributes().getNamedItem("outputtarget").getNodeValue());
    }

    public void setVideoBitrate(int value) {
        Node node = document.createAttribute("videobitrate");
        node.setNodeValue("" + value);
        output.getAttributes().setNamedItem(node);
    }

    public int getVideoBitrate() {
        return new Integer(output.getAttributes().getNamedItem("videobitrate").getNodeValue());
    }

    public void setAudioBitrate(FFMpeg.AudioRate value) {
        Node node = document.createAttribute("audiobitrate");
        node.setNodeValue(value.name());
        audios.getAttributes().setNamedItem(node);
    }

    public FFMpeg.AudioRate getAudioBitrate() {
        return FFMpeg.AudioRate.valueOf(audios.getAttributes().getNamedItem("audiobitrate").getNodeValue());
    }

    public void setOutputPreset(FFMpeg.Presets value) {
        Node node = document.createAttribute("outputpreset");
        node.setNodeValue(value.name());
        output.getAttributes().setNamedItem(node);
    }

    public FFMpeg.Presets getOutputPreset() {
        return FFMpeg.Presets.valueOf(output.getAttributes().getNamedItem("outputpreset").getNodeValue());
    }

    public void setOutputRTMPServer(String value) {
        Node node = document.createAttribute("rtmpserver");
        node.setNodeValue(value);
        output.getAttributes().setNamedItem(node);

    }

    public String getOutputRTMPServer() {
        return output.getAttributes().getNamedItem("rtmpserver").getNodeValue();
    }

    public void setOutputRTMPKey(String value) {
        Node node = document.createAttribute("rtmpkey");
        node.setNodeValue("" + value);
        output.getAttributes().setNamedItem(node);

    }

    public String getOutputRTMPKey() {
        return output.getAttributes().getNamedItem("rtmpkey").getNodeValue();
    }

    public void setAudioMicrophone(String value) {
        Node node = document.createAttribute("microphone");
        node.setNodeValue(value);
        audios.getAttributes().setNamedItem(node);

    }

    public String getAudioMicrophone() {
        return audios.getAttributes().getNamedItem("microphone").getNodeValue();
    }

    public void setAudioSystem(String value) {
        Node node = document.createAttribute("audiosystem");
        node.setNodeValue(value);
        audios.getAttributes().setNamedItem(node);
    }

    public String getAudioSystem() {
        return audios.getAttributes().getNamedItem("audiosystem").getNodeValue();
    }

    public void setShortcutsCapture(String value) {
        Node node = document.createAttribute("shortcutcapture");
        node.setNodeValue(value);
        settings.getAttributes().setNamedItem(node);
    }

    public String getShortcutCapture() {
        return settings.getAttributes().getNamedItem("shortcutcapture").getNodeValue();
    }

    public void setOutputVideoFolder(String value) {
        Node node = document.createAttribute("outputvideofolder");
        node.setNodeValue(value);
        output.getAttributes().setNamedItem(node);

    }

    public String getOutputVideoFolder() {
        return output.getAttributes().getNamedItem("outputvideofolder").getNodeValue();
    }

    public void setBackgroundMusic(File bgMusic) {
        Node node = document.createAttribute("backgroundmusic");
        if (bgMusic == null) {
            node.setNodeValue("");
        } else {
            node.setNodeValue(bgMusic.getAbsolutePath());
        }
        settings.getAttributes().setNamedItem(node);
    }

    public File getBackgroundMusic() {
        File retValue = null;
        if (settings.getAttributes().getNamedItem("backgroundmusic") != null) {
            String f = settings.getAttributes().getNamedItem("backgroundmusic").getNodeValue();
            retValue = new File(f);
            if (f.length() == 0 || !retValue.exists()) {
                retValue = null;
            }
        }
        return retValue;
    }

    public void reset() {
        NodeList nodes = root.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            root.removeChild(nodes.item(i));
        }
    }

    public void addSource(Source source) {
        String nodeName = "";
        switch (source.getType()) {
            case Desktop:
                nodeName = "desktop";
                break;
            case Image:
                nodeName = "image";
                break;
            case LabelText:
                nodeName = "label";
                break;
            case Webcam:
                nodeName = "webcam";
                break;
            case Frame:
                nodeName = "frame";
                break;
            case Custom:
                nodeName = "custom";
                break;
        }
        Node node = document.createElement(nodeName);
        Node capx = document.createAttribute("capturex");
        Node capy = document.createAttribute("capturey");
        
        //This is for the layouts
        
        for (Source.View v : source.getViews()) {
            Node nodeView = document.createElement("view");
            
            Node viewName = document.createAttribute("name");
            Node x = document.createAttribute("x");
            Node y = document.createAttribute("y");
            Node w = document.createAttribute("w");
            Node h = document.createAttribute("h");
            Node alpha = document.createAttribute("alpha");
            Node order = document.createAttribute("order");
            Node remoteDisplay = document.createAttribute("display");

            viewName.setNodeValue(v.ViewName);
            x.setNodeValue("" + v.X);
            y.setNodeValue("" + v.Y);
            w.setNodeValue("" + v.Width);
            h.setNodeValue("" + v.Height);
            alpha.setNodeValue("" + v.Alpha);
            order.setNodeValue("" + v.Order);
            remoteDisplay.setNodeValue("" + v.remoteDisplay);

            nodeView.getAttributes().setNamedItem(x);
            nodeView.getAttributes().setNamedItem(y);
            nodeView.getAttributes().setNamedItem(w);
            nodeView.getAttributes().setNamedItem(h);
            nodeView.getAttributes().setNamedItem(alpha);
            nodeView.getAttributes().setNamedItem(order);
            nodeView.getAttributes().setNamedItem(remoteDisplay);
            nodeView.getAttributes().setNamedItem(viewName);
            node.appendChild(nodeView);
        }

        Node id = document.createAttribute("id");
        Node type = document.createAttribute("type");
        Node foreg = document.createAttribute("fg");
        Node backg = document.createAttribute("bg");
        Node backgroundAreaColor = document.createAttribute("bgAreaColor");
        Node fontg = document.createAttribute("font");
        Node fontSize = document.createAttribute("fontsize");
        Node timeStart = document.createAttribute("start");
        Node timeEnd = document.createAttribute("end");
        Node transitionStart = document.createAttribute("transstart");
        Node transitionStop = document.createAttribute("transstop");
        Node effectFilter = document.createAttribute("effect");

        capx.setNodeValue("" + source.getCaptureX());
        capy.setNodeValue("" + source.getCaptureY());

        id.setNodeValue("" + source.getID());
        foreg.setNodeValue("" + source.getForegroundColor());
        backg.setNodeValue("" + source.getBackgroundColor());
        backgroundAreaColor.setNodeValue(""+source.getBackgroundAreaColor());
        fontg.setNodeValue(source.getFontName());
        fontSize.setNodeValue(""+source.getFontSize());
        timeStart.setNodeValue(source.getStartTime() + "");
        timeEnd.setNodeValue(source.getEndTime() + "");
        transitionStart.setNodeValue(source.getTransitionStart().name());
        transitionStop.setNodeValue(source.getTransitionStop().name());
        effectFilter.setNodeValue(source.getEffect().name());
        switch (source.getType()) {
            case LabelText:
                type.setNodeValue("text");
                break;
            default:
                type.setNodeValue("");
                break;
        }
        
        node.getAttributes().setNamedItem(capx);
        node.getAttributes().setNamedItem(capy);
        node.getAttributes().setNamedItem(id);
        node.getAttributes().setNamedItem(type);
        node.getAttributes().setNamedItem(foreg);
        node.getAttributes().setNamedItem(backg);
        node.getAttributes().setNamedItem(fontg);
        node.getAttributes().setNamedItem(timeStart);
        node.getAttributes().setNamedItem(timeEnd);
        node.getAttributes().setNamedItem(transitionStart);
        node.getAttributes().setNamedItem(transitionStop);
        node.getAttributes().setNamedItem(effectFilter);
        node.getAttributes().setNamedItem(backgroundAreaColor);
        node.getAttributes().setNamedItem(fontSize);
        root.appendChild(node);
    }

    private Source[] getDesktops() {
        NodeList nodes = document.getElementsByTagName("desktop");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            Node n = nodes.item(i);
            s.setType(SourceType.Desktop);

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());
            if (n.getAttributes().getNamedItem("capturex") != null) {
                s.setCaptureX((int) new Integer(n.getAttributes().getNamedItem("capturex").getNodeValue()));
                s.setCaptureY((int) new Integer(n.getAttributes().getNamedItem("capturey").getNodeValue()));
            } else {
                s.setCaptureX(0);
                s.setCaptureY(0);
            }
            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(Integer.parseInt(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundColor(Integer.parseInt(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundColor(0);
            }
            
            sources[i] = s;
        }
        return sources;
    }
    private Source[] getCustoms() {
        NodeList nodes = document.getElementsByTagName("custom");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            Node n = nodes.item(i);
            s.setType(SourceType.Custom);

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());
            if (n.getAttributes().getNamedItem("capturex") != null) {
                s.setCaptureX((int) new Integer(n.getAttributes().getNamedItem("capturex").getNodeValue()));
                s.setCaptureY((int) new Integer(n.getAttributes().getNamedItem("capturey").getNodeValue()));
            } else {
                s.setCaptureX(0);
                s.setCaptureY(0);
            }
            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(Integer.parseInt(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundColor(Integer.parseInt(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundColor(0);
            }
            sources[i] = s;
        }
        return sources;
    }

    private Source[] getWebcams() {
        NodeList nodes = document.getElementsByTagName("webcam");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            s.setType(SourceType.Webcam);
            Node n = nodes.item(i);
            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            sources[i] = s;
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(Integer.parseInt(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundColor(Integer.parseInt(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundColor(0);
            }
        }
        return sources;
    }

    public ArrayList<Source> getSources() {
        ArrayList<Source> list = new ArrayList<>();
        list.addAll(Arrays.asList(getImages()));
        list.addAll(Arrays.asList(getWebcams()));
        list.addAll(Arrays.asList(getDesktops()));
        list.addAll(Arrays.asList(getLabels()));
        list.addAll(Arrays.asList(getFrames()));
        list.addAll(Arrays.asList(getCustoms()));
        list.sort((Source o1, Source o2) -> o1.getViews().get(o1.getCurrentViewIndex()).Order - o2.getViews().get(o2.getCurrentViewIndex()).Order);
        return list;
    }

    private void loadView(Source s, Node n) {
        Source.View view = new Source.View();
        s.getViews().add(view);
        s.setCurrentViewIndex(0);
        view.X = new Integer(n.getAttributes().getNamedItem("x").getNodeValue());
        view.Y = new Integer(n.getAttributes().getNamedItem("y").getNodeValue());
        view.Width = new Integer(n.getAttributes().getNamedItem("w").getNodeValue());
        view.Height = new Integer(n.getAttributes().getNamedItem("h").getNodeValue());
        view.Alpha = new Float(n.getAttributes().getNamedItem("alpha").getNodeValue());
        view.Order = new Integer(n.getAttributes().getNamedItem("order").getNodeValue());
        if (n.getAttributes().getNamedItem("display") != null) {
            view.remoteDisplay = Boolean.parseBoolean(n.getAttributes().getNamedItem("display").getNodeValue());
        } else {
            view.remoteDisplay = true;
        }
    }

    private Source[] getImages() {
        NodeList nodes = document.getElementsByTagName("image");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            s.setType(SourceType.Image);
            Node n = nodes.item(i);
            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(Integer.parseInt(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundColor(Integer.parseInt(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundColor(0);
            }
            sources[i] = s;
        }
        return sources;
    }

    private Source[] getFrames() {
        NodeList nodes = document.getElementsByTagName("frame");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            s.setType(SourceType.Frame);
            Node n = nodes.item(i);
            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(Integer.parseInt(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundColor(Integer.parseInt(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundColor(0);
            }
            sources[i] = s;
        }
        return sources;
    }

    private Source[] getLabels() {
        NodeList nodes = document.getElementsByTagName("label");
        Source[] sources = new Source[nodes.getLength()];
        for (int i = 0; i < sources.length; i++) {
            Source s = new Source(0);
            s.setType(SourceType.LabelText);
            Node n = nodes.item(i);
            s.setID(n.getAttributes().getNamedItem("id").getNodeValue());

            if (n.getAttributes().getNamedItem("x") != null) {
                loadView(s, n);
            } else {
                // Load multiple views...
                for (int j = 0;j < n.getChildNodes().getLength();j++){
                    Node view = n.getChildNodes().item(j);
                    if (view.getNodeName().equals("view")){
                        loadView(s, view);
                    }
                }
            }

            // IF is required since not available in version 3.0.0
            if (n.getAttributes().getNamedItem("fg") != null) {
                s.setForegroundColor((int) new Integer(n.getAttributes().getNamedItem("fg").getNodeValue()));
                s.setBackgroundColor((int) new Integer(n.getAttributes().getNamedItem("bg").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("font") != null) {
                s.setFontName(n.getAttributes().getNamedItem("font").getNodeValue());
            }
            if (n.getAttributes().getNamedItem("start") != null) {
                s.setStartTime(Long.parseLong(n.getAttributes().getNamedItem("start").getNodeValue()));
                s.setEndTime(Long.parseLong(n.getAttributes().getNamedItem("end").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("transstart") != null) {
                s.setTransitionStart(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstart").getNodeValue()));
                s.setTransitionStop(Transition.NAMES.valueOf(n.getAttributes().getNamedItem("transstop").getNodeValue()));
            }
            if (n.getAttributes().getNamedItem("effect") != null) {
                s.setEffect(Effect.eEffects.valueOf(n.getAttributes().getNamedItem("effect").getNodeValue()));
            } else {
                s.setEffect(Effect.eEffects.None);
            }
            if (n.getAttributes().getNamedItem("fontsize") != null) {
                s.setFontSize(new Integer(n.getAttributes().getNamedItem("fontsize").getNodeValue()));
            } else {
                s.setFontSize(20);
            }
            if (n.getAttributes().getNamedItem("bgAreaColor") != null) {
                s.setBackgroundAreaColor(new Integer(n.getAttributes().getNamedItem("bgAreaColor").getNodeValue()));
            } else {
                s.setBackgroundAreaColor(0);
            }
            sources[i] = s;
        }
        return sources;
    }

    public void load(File file) throws IOException, ParserConfigurationException, SAXException {
        document = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
        root = document.getElementsByTagName("screenstudio").item(0);
        audios = document.getElementsByTagName("audios").item(0);
        output = document.getElementsByTagName("output").item(0);
        settings = document.getElementsByTagName("settings").item(0);
    }

    public void save(File file) throws TransformerConfigurationException, TransformerException {
        document.normalizeDocument();
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        Result fileOutput = new StreamResult(file);
        transformer.transform(new DOMSource(document), fileOutput);
    }
}
