/* Copyright 2008 we-lab-doc! (http://www.we-lab-doc.com/)
 *
 * Licensed 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.
 */
import org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteQueryPersistentMethod
import com.we_lab_doc.spacecard.plugin.utils.QueryExecuter
import com.we_lab_doc.spacecard.plugin.utils.DomainClassNameConverter
import com.we_lab_doc.spacecard.plugin.utils.FindAllPersistentMethod

/**
 * @author Shigeru GOUGI
 * @since 0.1
 *        <p/>
 *        Created: March 4, 2008
 */
class DomainModelHelperGrailsPlugin {
    def version = 0.1
    def author = "Shigeru GOUGI"
    def dependsOn = [:]
    def queryExecuter = null
    def watchedResources = [ "file:./grails-app/domains/**/*.groovy",
                             "file:./plugins/*/grails-app/domains/**/*.groovy" ]
    
    def doWithDynamicMethods = { ctx ->
    	def sessionFactory = ctx.sessionFactory
    	def cnv = new DomainClassNameConverter(application.domainClasses)
	    for (dc in application.domainClasses) {
	    	registerMethods(application, sessionFactory, dc, cnv)
	    }
        def executeQueryPersistentMethod = new ExecuteQueryPersistentMethod(sessionFactory, application.classLoader)    	
    	this.queryExecuter = new QueryExecuter(executeQueryPersistentMethod, cnv)
    }
	def onChange = { event ->
		if(event.source) {
			event.manager?.getGrailsPlugin("domainModelHelper")?.doWithDynamicMethods(event.ctx)
		}
	}
    def getQueryExecuter() {
    	return this.queryExecuter
    }
    private registerMethods(def application, def sessionFactory, def dc, def cnv) {
        def findAllPersistentMethod = new FindAllPersistentMethod(sessionFactory, application.classLoader)    		    	
        MetaClass mc = dc.metaClass
       	def name = mc.javaClass.simpleName
   		def asKeyword = mc.javaClass.simpleName.toLowerCase()[0]
        mc.'static'.fetch = {Object example ->
	   		def newExample = cnv.convert("from ${name} as ${asKeyword} ${example}")
	  		return findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample] as Object[])
	   	}
	    mc.'static'.fetch = {Object example, Map args ->
	        def newExample = cnv.convert("from ${name} as ${asKeyword} ${example}")            		
			findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample, args] as Object[])            		
	   	}
        mc.'static'.select = {Object example ->
       		def newExample = cnv.convert("select ${asKeyword} from ${name} as ${asKeyword} ${example}")
      		return findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample] as Object[])
       	}
        mc.'static'.select = {Object example, Map args ->
	        def newExample = cnv.convert("select ${asKeyword} from ${name} as ${asKeyword} ${example}")            		
    		findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample, args] as Object[])            		
       	}
        mc.'static'.selectDistinct = {Object example ->
       		def newExample = cnv.convert("select distinct ${asKeyword} from ${name} as ${asKeyword} ${example}")
      		return findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample] as Object[])
       	}
        mc.'static'.selectDistinct = {Object example, Map args ->
        	def newExample = cnv.convert("select distinct ${asKeyword} from ${name} as ${asKeyword} ${example}")            		
    		findAllPersistentMethod.invoke(mc.javaClass, "findAll", [newExample, args] as Object[])            		
       	}
    }
}