package com.k_int.commons.installer.dbsetup;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.*;
import java.io.InputStream;
import java.net.URL;
import org.apache.commons.digester.*;
import org.apache.commons.digester.xmlrules.*;
import org.hibernate.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;


public class DatabaseSynchronizer {

  public static Log log = LogFactory.getLog(DatabaseSynchronizer.class);

  private static Config config = null;

  public DatabaseSynchronizer() {
  }

  public void setConfig(Config config) {
    log.debug("Config");   
    this.config = config;
  }

  public Object processCreateOrUpdate(com.k_int.commons.installer.dbsetup.CreateOrUpdateRequest crud_request) {
    log.debug("DatabaseSynchronizer::processCreateOrUpdate");
    Object result = createOrUpdate(crud_request);
    return result;
  }

  public static Object createOrUpdate(com.k_int.commons.installer.dbsetup.CreateOrUpdateRequest crud_request) {  
    log.debug("DatabaseSynchronizer::createOrUpdate : " + crud_request.getClassName());
    Object result = null;

    RegisteredClassDef reg_class_def = config.lookupClassDef(crud_request.getClassName());
    if ( reg_class_def != null ) {
      org.hibernate.Session sess = null;
      try {
        // 1 : Retrieve class lookup information
        log.debug("Located registered class def.. Looking up any existing instances in database");

        org.hibernate.SessionFactory factory = (org.hibernate.SessionFactory) config.getAppCtx().getBean(config.getSessFactoryName());
        sess = factory.openSession();

        // 2 : Attempt to lookup an instance using any of the available data
        boolean located = false;
        for ( java.util.Iterator i = reg_class_def.getLookupSets().iterator(); ( i.hasNext() && !located) ; ) {
          List lookup_set = (List) i.next();
          log.debug("Processing lookup set : "+lookup_set);
          List types = new ArrayList();
          List values = new ArrayList();
          Criteria lookup_query = sess.createCriteria(crud_request.getClassName());
          for ( java.util.Iterator i2 = lookup_set.iterator(); i2.hasNext(); ) {
            String prop_name = (String) i2.next();
            lookup_query.add(org.hibernate.criterion.Restrictions.eq(prop_name,crud_request.getParams().get(prop_name)));
          }
          result = lookup_query.uniqueResult();
          if ( result != null ) {
            log.debug("  found");
            located = true;
          }
          else {
            log.debug("  Not found");
          }
        }
        // 3 : Found?
        if ( located ) {
          // 3.1. : Yes, update according to new properties
        }
        else {
          Object o = createInstance(crud_request.getClassName());
          // 3.2  : No, Create and set properties
          log.debug("Creating new instance of "+crud_request.getClassName());
          for ( java.util.Iterator i3 = crud_request.getParams().keySet().iterator(); i3.hasNext(); ) {
            String key = (String) i3.next();
            log.debug("Process "+key+" = "+crud_request.getParams().get(key));
          }
        }
      }
      finally {
        if ( sess != null ) {
          try { sess.close(); } catch ( Exception e ) { } 
        }
      }
    }
    else {
      log.warn("Unable to locate class def for "+crud_request.getClassName());
    }

    return result;
  }

  public static Object createInstance(String classname) {
    Object result = null;
    try {
      Class c = Class.forName(classname);
      result = c.newInstance();
    }
    catch ( java.lang.ClassNotFoundException cnfe ) {
      log.error("Problem creating instance ",cnfe);
    }
    catch ( java.lang.InstantiationException ie ) {
      log.error("Problem creating instance ",ie);
    }
    catch ( java.lang.IllegalAccessException iae ) {
      log.error("Problem creating instance ",iae);
    }
    return result;
  }
}
