/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.entityext.data;

import java.net.URL;
import java.net.MalformedURLException;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.io.File;

import javolution.util.FastList;

import org.ofbiz.base.container.Container;
import org.ofbiz.base.container.ContainerConfig;
import org.ofbiz.base.container.ContainerException;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilURL;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.DelegatorFactory;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.jdbc.DatabaseUtil;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.util.EntityDataLoader;
import org.ofbiz.service.ServiceDispatcher;
import org.ofbiz.service.ThreadContext;


/**
 * Some utility routines for loading seed data.
 */
public class EntityDataLoadContainer implements Container {

    public static final String module = EntityDataLoadContainer.class.getName();

    protected String overrideDelegator = null;
    protected String overrideGroup = null;
    protected String configFile = null;
    protected String readers = null;
    protected String directory = null;
    protected List<String> files = FastList.newInstance();
    protected String component = null;
    protected boolean useDummyFks = false;
    protected boolean maintainTxs = false;
    protected boolean tryInserts = false;
    protected boolean repairColumns = false;
    protected boolean dropPks = false;
    protected boolean createPks = false;
    protected boolean dropConstraints = false;
    protected boolean createConstraints = false;
    protected int txTimeout = -1;

    public EntityDataLoadContainer() {
        super();
    }

    /**
     * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String)
     */
    public void init(String[] args, String configFile) throws ContainerException {
        this.configFile = configFile;
        // disable job scheduler, JMS listener and startup services
        ServiceDispatcher.enableJM(false);
        ServiceDispatcher.enableJMS(false);
        ServiceDispatcher.enableSvcs(false);

        /*
           install arguments:
           readers (none, all, seed, demo, ext, etc - configured in entityengine.xml and associated via ofbiz-component.xml)
           timeout (transaction timeout default 7200)
           delegator (overrides the delegator name configured for the container)
           group (overrides the entity group name configured for the container)
           dir (imports all XML files in a directory)
           file (import a specific XML file)

           Example:
           $ java -jar ofbiz.jar -install -readers=seed,demo,ext -timeout=7200 -delegator=default -group=org.ofbiz
           $ java -jar ofbiz.jar -install -file=/tmp/dataload.xml
        */
        if (args != null) {
            for (String argument: args) {
                // arguments can prefix w/ a '-'. Just strip them off
                if (argument.startsWith("-")) {
                    int subIdx = 1;
                    if (argument.startsWith("--")) {
                        subIdx = 2;
                    }
                    argument = argument.substring(subIdx);
                }

                // parse the arguments
                String argumentName;
                String argumentVal;
                if (argument.indexOf("=") != -1) {
                    argumentName = argument.substring(0, argument.indexOf("="));
                    argumentVal = argument.substring(argument.indexOf("=") + 1);
                } else {
                    argumentName = argument;
                    argumentVal = "";
                }
                Debug.log("Install Argument - " + argumentName + " = " + argumentVal, module);

                if ("readers".equalsIgnoreCase(argumentName)) {
                    this.readers = argumentVal;
                } else if ("timeout".equalsIgnoreCase(argumentName)) {
                    try {
                        this.txTimeout = Integer.parseInt(argumentVal);
                    } catch (Exception e) {
                        this.txTimeout = -1;
                    }
                } else if ("component".equalsIgnoreCase(argumentName)) {
                    this.component = argumentVal;
                } else if ("delegator".equalsIgnoreCase(argumentName)) {
                    this.overrideDelegator = argumentVal;
                } else if ("group".equalsIgnoreCase(argumentName)) {
                    this.overrideGroup = argumentVal;
                } else if ("file".equalsIgnoreCase(argumentName)) {
                    this.files.addAll(StringUtil.split(argumentVal, ","));
                } else if ("dir".equalsIgnoreCase(argumentName)) {
                    this.directory = argumentVal;
                } else if ("createfks".equalsIgnoreCase(argumentName)) {
                    this.useDummyFks = "true".equalsIgnoreCase(argumentVal);
                } else if ("maintainTxs".equalsIgnoreCase(argumentName)) {
                    this.maintainTxs = "true".equalsIgnoreCase(argumentVal);
                } else if ("inserts".equalsIgnoreCase(argumentName)) {
                    this.tryInserts = "true".equalsIgnoreCase(argumentVal);
                } else if ("repair-columns".equalsIgnoreCase(argumentName)) {
                    if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) {
                        repairColumns = true;
                    }
                } else if ("drop-pks".equalsIgnoreCase(argumentName)) {
                    if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) {
                        dropPks = true;                        
                    }
                } else if ("create-pks".equalsIgnoreCase(argumentName)) {
                    if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) {
                        createPks = true;
                    } 
                } else if ("drop-constraints".equalsIgnoreCase(argumentName)) {
                    if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) {
                        dropConstraints = true;                      
                    }
                } else if ("create-constraints".equalsIgnoreCase(argumentName)) {
                    if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) {
                        createConstraints = true;
                    }
                } else if ("help".equalsIgnoreCase(argumentName)) {
                    Debug.log("--------------------------------------", module);
                    Debug.log("java -jar ofbiz.jar -install [options]", module);
                    Debug.log("-component=[name] .... only load from a specific component");
                    Debug.log("-delegator=[name] .... use the defined delegator (default-no-eca", module);
                    Debug.log("-group=[name] ........ override the entity group (org.ofbiz)", module);
                    Debug.log("-file=[path] ......... load a single from from location", module);
                    Debug.log("-createfks ........... create dummy (placeholder) FKs", module);
                    Debug.log("-maintainTxs ......... maintain timestamps in data file", module);
                    Debug.log("-inserts ............. use mostly inserts option", module);
                    Debug.log("-repair-columns ........... repair column sizes", module);
                    Debug.log("-drop-pks ............ drop primary keys", module);
                    Debug.log("-create-pks .......... create primary keys", module);
                    Debug.log("-drop-constraints..... drop indexes and foreign keys before loading", module);
                    Debug.log("-create-constraints... create indexes and foreign keys after loading (default is true w/ drop-constraints)", module);
                    Debug.log("-help ................ display this information", module);
                    System.exit(1);
                }

                // special case
                if (this.readers == null && (!this.files.isEmpty() || this.directory != null)) {
                    this.readers = "none";
                }
            }
        }
    }

    /**
     * @see org.ofbiz.base.container.Container#start()
     */
    public boolean start() throws ContainerException {
        ContainerConfig.Container cfg = ContainerConfig.getContainer("dataload-container", configFile);
        ContainerConfig.Container.Property delegatorNameProp = cfg.getProperty("delegator-name");
        ContainerConfig.Container.Property entityGroupNameProp = cfg.getProperty("entity-group-name");

        String delegatorName = null;
        String entityGroupName = null;

        if (delegatorNameProp == null || delegatorNameProp.value == null || delegatorNameProp.value.length() == 0) {
            throw new ContainerException("Invalid delegator-name defined in container configuration");
        } else {
            delegatorName = delegatorNameProp.value;
        }

        if (entityGroupNameProp == null || entityGroupNameProp.value == null || entityGroupNameProp.value.length() == 0) {
            throw new ContainerException("Invalid entity-group-name defined in container configuration");
        } else {
            entityGroupName = entityGroupNameProp.value;
        }

        // parse the pass in list of readers to use
        List<String> readerNames = null;
        if (this.readers != null && !"none".equalsIgnoreCase(this.readers)) {
            if (this.readers.indexOf(",") == -1) {
                readerNames = FastList.newInstance();
                readerNames.add(this.readers);
            } else {
                readerNames = StringUtil.split(this.readers, ",");
            }
        }

        String delegatorNameToUse = overrideDelegator != null ? overrideDelegator : delegatorName;
        String groupNameToUse = overrideGroup != null ? overrideGroup : entityGroupName;
        GenericDelegator delegator = DelegatorFactory.getGenericDelegator(delegatorNameToUse);
        if (delegator == null) {
            throw new ContainerException("Invalid delegator name!");
        }

        String helperName = delegator.getGroupHelperName(groupNameToUse);
        if (helperName == null) {
            throw new ContainerException("Unable to locate the datasource helper for the group [" + groupNameToUse + "]");
        }

        // get the database util object
        DatabaseUtil dbUtil = new DatabaseUtil(helperName);
        Map<String, ModelEntity> modelEntities;
        try {
            modelEntities = delegator.getModelEntityMapByGroup(groupNameToUse);
        } catch (GenericEntityException e) {
            throw new ContainerException(e.getMessage(), e);
        }        
        TreeSet<String> modelEntityNames = new TreeSet<String>(modelEntities.keySet());

        // Set up the execution context
        ThreadContext.runUnprotected();
        ThreadContext.setDelegator(delegator);
        ThreadContext.pushExecutionArtifact(module, "EntityDataLoad");
        try {
            // check for drop index/fks
            if (dropConstraints) {                   
                List<String> messages = FastList.newInstance();

                Debug.logImportant("Dropping foreign key indcies...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.deleteForeignKeyIndices(modelEntity, messages);
                    }
                }

                Debug.logImportant("Dropping declared indices...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.deleteDeclaredIndices(modelEntity, messages);
                    }
                }

                Debug.logImportant("Dropping foreign keys...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.deleteForeignKeys(modelEntity, modelEntities, messages);
                    }
                }

                if (messages.size() > 0) {
                    if (Debug.infoOn()) {
                        for (String message : messages) {
                            Debug.logInfo(message, module);
                        }
                    }
                }
            }

            // drop pks
            if (dropPks) {
                List<String> messages = FastList.newInstance();
                Debug.logImportant("Dropping primary keys...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName); 
                    if (modelEntity != null) {
                        dbUtil.deletePrimaryKey(modelEntity, messages);
                    }
                }

                if (messages.size() > 0) {
                    if (Debug.infoOn()) {
                        for (String message : messages) {
                            Debug.logInfo(message, module);
                        }
                    }
                }
            }

            // repair columns
            if (repairColumns) {
                List<String> fieldsToRepair = FastList.newInstance();
                List<String> messages = FastList.newInstance();
                dbUtil.checkDb(modelEntities, fieldsToRepair, messages, false, false, false, false);
                if (fieldsToRepair.size() > 0) {
                    messages = FastList.newInstance();
                    dbUtil.repairColumnSizeChanges(modelEntities, fieldsToRepair, messages);
                    if (messages.size() > 0) {
                        if (Debug.infoOn()) {
                            for (String message : messages) {
                                Debug.logInfo(message, module);
                            }
                        }
                    }
                }
            }

            // get the reader name URLs first
            List<URL> urlList = null;
            if (readerNames != null) {
                urlList = EntityDataLoader.getUrlList(helperName, component, readerNames);
            } else if (!"none".equalsIgnoreCase(this.readers)) {
                urlList = EntityDataLoader.getUrlList(helperName, component);
            }

            // need a list if it is empty
            if (urlList == null) {
                urlList = FastList.newInstance();
            }

            // add in the defined extra files
            for (String fileName: this.files) {
                URL fileUrl = UtilURL.fromResource((String) fileName);
                if (fileUrl != null) {
                    urlList.add(fileUrl);
                }
            }

            // next check for a directory of files
            if (this.directory != null) {
                File dir = new File(this.directory);
                if (dir.exists() && dir.isDirectory() && dir.canRead()) {
                    File[] fileArray = dir.listFiles();
                    if (fileArray != null && fileArray.length > 0) {
                        for (File file: fileArray) {
                            if (file.getName().toLowerCase().endsWith(".xml")) {
                                try {
                                    urlList.add(file.toURI().toURL());
                                } catch (MalformedURLException e) {
                                    Debug.logError(e, "Unable to load file (" + file.getName() + "); not a valid URL.", module);
                                }
                            }
                        }
                    }
                }
            }

            // process the list of files
            NumberFormat changedFormat = NumberFormat.getIntegerInstance();
            changedFormat.setMinimumIntegerDigits(5);
            changedFormat.setGroupingUsed(false);

            List<Object> errorMessages = FastList.newInstance();
            List<String> infoMessages = FastList.newInstance();
            int totalRowsChanged = 0;
            if (UtilValidate.isNotEmpty(urlList)) {
                Debug.logImportant("=-=-=-=-=-=-= Doing a data load with the following files:", module);
                for (URL dataUrl: urlList) {
                    Debug.logImportant(dataUrl.toExternalForm(), module);
                }

                Debug.logImportant("=-=-=-=-=-=-= Starting the data load...", module);

                for (URL dataUrl: urlList) {
                    try {
                        int rowsChanged = EntityDataLoader.loadData(dataUrl, helperName, delegator, errorMessages, txTimeout, useDummyFks, maintainTxs, tryInserts);
                        totalRowsChanged += rowsChanged;
                        infoMessages.add(changedFormat.format(rowsChanged) + " of " + changedFormat.format(totalRowsChanged) + " from " + dataUrl.toExternalForm());
                    } catch (GenericEntityException e) {
                        Debug.logError(e, "Error loading data file: " + dataUrl.toExternalForm(), module);
                    }
                }
            } else {
                Debug.logImportant("=-=-=-=-=-=-= No data load files found.", module);
            }

            if (infoMessages.size() > 0) {
                Debug.logImportant("=-=-=-=-=-=-= Here is a summary of the data load:", module);
                for (String message: infoMessages) {
                    Debug.logImportant(message, module);
                }
            }

            if (errorMessages.size() > 0) {
                Debug.logImportant("The following errors occured in the data load:", module);
                for (Object message: errorMessages) {
                    Debug.logImportant(message.toString(), module);
                }
            }

            Debug.logImportant("=-=-=-=-=-=-= Finished the data load with " + totalRowsChanged + " rows changed.", module);

            // create primary keys
            if (createPks) {
                List<String> messages = FastList.newInstance();

                Debug.logImportant("Creating primary keys...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.createPrimaryKey(modelEntity, messages);
                    }
                }
                if (messages.size() > 0) {
                    if (Debug.infoOn()) {
                        for (String message : messages) {
                            Debug.logInfo(message, module);
                        }
                    }
                }
            }

            // create constraints
            if (createConstraints) {                   
                List<String> messages = FastList.newInstance();

                Debug.logImportant("Creating foreign keys...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.createForeignKeys(modelEntity, modelEntities, messages);
                    }
                }

                Debug.logImportant("Creating foreign key indcies...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.createForeignKeyIndices(modelEntity, messages);
                    }
                }

                Debug.logImportant("Creating declared indices...", module);
                for (String entityName : modelEntityNames) {
                    ModelEntity modelEntity = modelEntities.get(entityName);
                    if (modelEntity != null) {
                        dbUtil.createDeclaredIndices(modelEntity, messages);
                    }
                }

                if (messages.size() > 0) {
                    if (Debug.infoOn()) {
                        for (String message : messages) {
                            Debug.logInfo(message, module);
                        }
                    }
                }
            }
        } finally {
            ThreadContext.popExecutionArtifact();
            ThreadContext.endRunUnprotected();
        }
        return true;
    }

    /**
     * @see org.ofbiz.base.container.Container#stop()
     */
    public void stop() throws ContainerException {
    }
}
