/*
 * Copyright 2009, 2010 Lari Natri <lari.natri@gmail.com>
 *
 *  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/>.
 */

package compid.application;

import net.aavalla.utils.general.CastHelper;
import net.aavalla.utils.jobpool.Job;
import net.aavalla.utils.jobpool.JobCategory;
import net.aavalla.utils.jobpool.JobPriority;
import compid.data.DAOException;
import compid.data.DAOFactory;
import compid.data.DAOFactory.DBType;
import compid.data.SettingDAO;
import compid.data.tuples.Setting;
import java.util.Properties;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

/**
 *
 * @author larva
 */
class DatabaseInitializer extends Job<Boolean,CompidApp> {
    
    DatabaseInitializer(CompidApp app) {
        super(app);
        this.setName("Database Initializer");
        this.setSilent(true);
        this.setPriority(JobPriority.IMMEDIATE);
        this.addCategory(JobCategory.DB_WRITE);
        this.addConflictingCategory(JobCategory.DB_READ);
        this.addConflictingCategory(JobCategory.DB_WRITE);
        
    }

    @Override
    protected Boolean work(CompidApp app) throws Throwable {
        this.reportStatus("Initializing...");
        Properties compidProps = app.getSoftProperties();
        final String url = compidProps.getProperty("db.url"); //NOI18N
        final String user = compidProps.getProperty("db.user"); //NOI18N
        final String pass = compidProps.getProperty("db.password"); //NOI18N
        boolean exists = false;
        try {
            exists = DAOFactory.dbExists(DBType.DERBYEMBEDDED, url, user, pass);
        } catch (DAOException ex) {
            if (ex.getExceptionType().equals(DAOException.ExceptionType.ANOTHERINSTANCEHASBOOTED)) {
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override public void run() {
                            JOptionPane.showMessageDialog(CompidApp.getApplication().getMainFrame(),
                                        "You are trying to use an embedded database which seems to be already\n" +
                                        "in use. Stop all other instances of Compid and try again. If you are\n" +
                                        "absolutely sure that the database is not in use, remove .lck files from\n" +
                                        "the database directory: "+url,
                                        "Database is in use",
                                         JOptionPane.ERROR_MESSAGE);
                            CompidApp.getApplication().exit();
                        }
                    });
                } catch (Exception swingEx) {}
            }
        }
        if (exists) {
            System.out.println("DEBUG: Database exists");
        } else {
            System.out.println("DEBUG: Database doesn't exist");
            try {
                SwingUtilities.invokeAndWait(new Runnable() {
                    @Override
                    public void run() {
                        boolean createDb = JOptionPane.showConfirmDialog(CompidApp.getApplication().getMainFrame(),
                                            "Database doesn't exist in "+url+"\n" +
                                            "Do you want to create it?", "Create database?", JOptionPane.YES_NO_OPTION) ==
                                            JOptionPane.YES_OPTION;
                        if (!createDb) {
                            CompidApp.getApplication().exit();
                        } else {
                            System.out.println("DEBUG: Creating database into "+url);
                        }
                    }
                });
            } catch (Exception swingEx) {}
        }

        DAOFactory.connectDB(DBType.DERBYEMBEDDED, url, user, pass, true);

        int dbVerMajApp = app.getHardResource().getInteger("Application.dbver.major"); // NOI18N
        int dbVerMinApp = app.getHardResource().getInteger("Application.dbver.minor"); // NOI18N
        SettingDAO setDAO = DAOFactory.getInstance().getSettingDAO();

        String errorText = null;

        if (exists) { // did exist, check db version

            Setting dbMaj = setDAO.get("DBVERMAJOR");
            Setting dbMin = setDAO.get("DBVERMAJOR");
            if (dbMaj==null || dbMin==null
                    || CastHelper.isInteger(dbMaj.getValue())==false
                    || CastHelper.isInteger(dbMin.getValue())==false) {
                errorText = "Database in " +url + "\n" +
                        "is in corrupt shape and cannot be used.";

            } else {
                int dbIsMaj = Integer.parseInt(dbMaj.getValue());
                int dbIsMin = Integer.parseInt(dbMin.getValue());
                if (dbIsMaj<dbVerMajApp) {
                    errorText = "Database in " + url + "\n" +
                            "is created with an older version of Compid and cannot be used. \n" +
                            "Please use old Compid or create a new database.";
                } else if (dbIsMaj>dbVerMajApp) {
                    errorText = "Database in " + url + "\n" +
                            "is created with a newer version of Compid and cannot be used. \n" +
                            "Please upgrade Compid or use another database.";
                }

            }
        } else { // didnn't exist, was created => add settings
            Setting dbMaj = new Setting("DBVERMAJOR", String.valueOf(dbVerMajApp),
                    "Database version (major)",1,0,0);
            Setting dbMin = new Setting("DBVERMINOR", String.valueOf(dbVerMinApp),
                    "Database version (major)",1,0,0);
            setDAO.addOrUpdate(dbMaj);
            setDAO.addOrUpdate(dbMin);
        }
        if (errorText!=null) {
            try {
                final String finalError = errorText;
                SwingUtilities.invokeAndWait(new Runnable() {
                    @Override
                    public void run() {
                        JOptionPane.showMessageDialog(CompidApp.getApplication().getMainFrame(),
                                finalError, "Database error", JOptionPane.ERROR_MESSAGE);
                    }
                });
            } catch (Exception swingEx) {
            } finally {
                CompidApp.getApplication().exit();
            }

        }
        app.getDatasetsHandler().refresh();
        this.reportStatus("Database online");
        return true;
    }



}
