package com.quantum.model.xml;

import java.sql.SQLException;

import com.quantum.model.Bookmark;
import com.quantum.model.Column;
import com.quantum.model.Entity;
import com.quantum.model.JDBCDriver;
import com.quantum.model.NotConnectedException;
import com.quantum.model.Schema;
import com.quantum.sql.metadata.MetaDataXMLInterface;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 * @author BC
 */
public class ModelToXMLConverter {
    
    private static final ModelToXMLConverter instance = new ModelToXMLConverter();
    
    private ModelToXMLConverter() {
    }
    
    public static ModelToXMLConverter getInstance() {
        return ModelToXMLConverter.instance;
    }

    public void createRoot(Document document) {
        document.appendChild(document.createElement("SAVED_DATA"));
    }
    public void convert(Element bookmarkRoot, JDBCDriver jdbcDriver) {
        Document document = bookmarkRoot.getOwnerDocument();
        Element driverNode = document.createElement("jdbcDriver");
        driverNode.setAttribute("name", jdbcDriver.getName());
        driverNode.setAttribute("version", jdbcDriver.getVersion());
        driverNode.setAttribute("type", jdbcDriver.getType());
        driverNode.setAttribute("className", jdbcDriver.getClassName());
        
        String[] fileNames = jdbcDriver.getJarFileNames();
        for (int i = 0, length = fileNames == null ? 0 : fileNames.length; i < length; i++) {
        	if (fileNames[i] != null) {
				Element fileName = document.createElement("jar");
				fileName.setAttribute("fileName", fileNames[i]);
				driverNode.appendChild(fileName);
        	}
		}
        
        bookmarkRoot.appendChild(driverNode);
    }

    public void convert(Element bookmarkRoot, Bookmark b) {
        Document document = bookmarkRoot.getOwnerDocument();
        Element bookmark = MetaDataXMLInterface.createElementText(bookmarkRoot,"bookmark", ""); //$NON-NLS-1$ //$NON-NLS-2$
        MetaDataXMLInterface.createElementText(bookmark,"name", b.getName()); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"username", b.getUsername()); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"password", b.getPassword()); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"prompt", b.getPromptForPassword() ? "true" : "false"); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"connect", b.getConnect()); //$NON-NLS-1$
		MetaDataXMLInterface.createElementText(bookmark,"autoCommit", b.isAutoCommit() ? "true" : "false"); //$NON-NLS-1$
		MetaDataXMLInterface.createElementText(bookmark,"autoCommitPreference", b.getAutoCommitPreference()); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"driver", b.getJDBCDriver().getClassName()); //$NON-NLS-1$
        MetaDataXMLInterface.createElementText(bookmark,"type", b.getJDBCDriver().getType()); //$NON-NLS-1$
        String[] fileNames = b.getJDBCDriver().getJarFileNames();
        for (int i = 0, length = fileNames == null ? 0 : fileNames.length; i < length; i++) {
			MetaDataXMLInterface.createElementText(bookmark,"driverLocation", fileNames[i]);
		}
        Element otherSchemas = (Element) bookmark.appendChild(document.createElement("Other_Schemas")); //$NON-NLS-1$
        otherSchemas.setAttribute("schemaRule", 
        		b.useAllSchemas() 
					? "useAll" 
					: b.useUsernameAsSchema() ? "useDefault" : "useSelected");
        
        Schema[] schemas = b.getSchemaSelections();
        for (int i = 0, length = (schemas == null) ? 0 : schemas.length; i < length; i++) {
            MetaDataXMLInterface.createElementText(
                otherSchemas,"schema", schemas[i].getName()); //$NON-NLS-1$
        }
        
        Entity[] quickList = b.getQuickListEntries();
        Element quickListEntity = document.createElement("quickList");
        for (int j = 0, length = (quickList == null) ? 0 : quickList.length;
            j < length;
            j++) {
            ModelToXMLConverter.getInstance().convert(quickListEntity, quickList[j]);
        }
        bookmark.appendChild(quickListEntity);
        convertQueryList(b, bookmark);
    }

    
    public void convert(Element parent, Entity entity) {
        convert(parent, entity, true);
    }
    public void convert(Element parent, Entity entity, boolean recurse) {
        Document document = parent.getOwnerDocument();
        Element element = document.createElement(getEntityDOMNodeName(entity));
        element.setAttribute("name", entity.getName());
        if (entity.getSchema() != null) {
            element.setAttribute("schema", entity.getSchema());
        }
        element.setAttribute("isSynonym", entity.isSynonym() ? "true" : "false");
        if (recurse) {
            try {
				convert(element, entity.getColumns());
			} catch (NotConnectedException e) {
			} catch (SQLException e) {
			}
        }
        parent.appendChild(element);
    }

    public void convert(Element element, Column[] columns) {
        for (int i = 0, length = (columns == null) ? 0 : columns.length;
            i < length;
            i++) {
            convert(element, columns[i]);
        }
    }

    public void convert(Element parent, Column column) {
        Document document = parent.getOwnerDocument();
        Element element = document.createElement("column");
        element.setAttribute("name", column.getName());
        element.setAttribute("type", column.getTypeName());
        element.setAttribute("primaryKey", column.isPrimaryKey() ? "true" : "false");
        element.setAttribute("nullable", column.isNullable() ? "true" : "false");
        if (column.isNumeric()) {
            if (column.getSize() > 0) {
                element.setAttribute("size", String.valueOf(column.getSize()));
            }
            if (column.getNumberOfFractionalDigits() > 0) {
                element.setAttribute("numberOfFractionalDigits", String.valueOf(column.getNumberOfFractionalDigits()));
            }
        } else {
            if (column.getSize() > 0) {
                element.setAttribute("size", String.valueOf(column.getSize()));
            }
        }
		if (column.getRemarks().length() > 0)
			MetaDataXMLInterface.createElementText(element, "remarks", column.getRemarks());
        parent.appendChild(element);
    }


    public String getEntityDOMNodeName(Entity entity) {
        if (Entity.TABLE_TYPE.equals(entity.getType())) {
            return "table";
        } else if (Entity.VIEW_TYPE.equals(entity.getType())) {
            return "view";
        } else if (Entity.SEQUENCE_TYPE.equals(entity.getType())) {
            return "sequence";
        } else {
            return "unknown";
        }
    }

    public void convertQueryList(
        Bookmark bookmark,
        Element parent) {
            
        Document document = parent.getOwnerDocument();
        String[] queryList = bookmark.getQueries();
        Element queryListEntity = document.createElement("queryList");
        for (int j = 0, length = (queryList == null) ? 0 : queryList.length;
            j < length;
            j++) {
            Element query = document.createElement("query");
            
            // will have more possibilities later
            Element queryString = document.createElement("queryString");
            Text queryText = document.createTextNode(queryList[j]);
            queryString.appendChild(queryText);
            query.appendChild(queryString);
            queryListEntity.appendChild(query);
        }
        parent.appendChild(queryListEntity);
    }
    
}