package org.openmrs.module.appframework.factory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.openmrs.module.appframework.domain.AppDescriptor;
import org.openmrs.module.appframework.domain.AppTemplate;
import org.openmrs.module.appframework.domain.Extension;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Component
public class AppConfigurationLoaderFactory implements AppFrameworkFactory {

    protected Log logger = LogFactory.getLog(getClass());

    private ObjectMapper objectMapper = new ObjectMapper();

    private PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();

    public AppConfigurationLoaderFactory() {
    	// Tell the parser to all // and /* style comments.
    	objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
    }
    
    @Override
    public List<AppTemplate> getAppTemplates() throws IOException {
        Resource[] appDefinitionJsonResources = resourceResolver.getResources("classpath*:/apps/*AppTemplates.json");
        List<AppTemplate> templates = new ArrayList<AppTemplate>();
        for (Resource appDefinitionResource : appDefinitionJsonResources) {
            List<AppTemplate> forResource;
            try {
                forResource = objectMapper.readValue(appDefinitionResource.getInputStream(), new TypeReference<List<AppTemplate>>() {});
                templates.addAll(forResource);
            } catch (IOException e) {
                logger.fatal("Error reading AppTemplates configuration file", e);
            }
        }
        return templates;
    }

    @Override
    public List<AppDescriptor> getAppDescriptors() throws IOException {
        Resource[] appDefinitionJsonResources = resourceResolver.getResources("classpath*:/apps/*app.json");
        List<AppDescriptor> appDescriptors = new ArrayList<AppDescriptor>();
        for (Resource appDefinitionResource : appDefinitionJsonResources) {
            try {
                List<AppDescriptor> appDescriptorsForResource = getAppDescriptorsForResource(appDefinitionResource.getInputStream());
                appDescriptors.addAll(appDescriptorsForResource);
            } catch (IOException e) {
                logger.fatal("Error reading app configuration file: " + appDefinitionResource.getFile().getPath(), e);
            }
        }
        return appDescriptors;
    }

    public List<AppDescriptor> getAppDescriptorsForResource(InputStream inputStream) throws IOException {
        return objectMapper.readValue(inputStream, new TypeReference<List<AppDescriptor>>() {});
    }

    @Override
    public List<Extension> getExtensions() throws IOException {
        Resource[] extensionDefinitionJsonResources = resourceResolver.getResources("classpath*:/apps/*extension.json");
        List<Extension> extensions = new ArrayList<Extension>();
        for (Resource extensionResource : extensionDefinitionJsonResources) {
            List<Extension> extensionsForResource;
            try {
                extensionsForResource = objectMapper.readValue(extensionResource.getInputStream(), new TypeReference<List<Extension>>() {});
                extensions.addAll(extensionsForResource);
            } catch (IOException e) {
                logger.fatal("Error reading extension configuration file: " + extensionResource.getFilename(), e);
            }
        }
        return extensions;
    }
}

@@ -47,93 +47,8 @@
 y;%0A%0A
-import org.apache.commons.logging.Log;%0Aimport org.apache.commons.logging.LogFactory;%0A
 impo
@@ -79,24 +79,24 @@
 JsonParser;%0A
+
 import org.c
@@ -350,24 +350,81 @@
 .Extension;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 import org.s
@@ -799,16 +799,19 @@
 cted Log
+ger
  logger 
@@ -815,16 +815,19 @@
 er = Log
+ger
 Factory.
@@ -832,16 +832,19 @@
 y.getLog
+ger
 (getClas
@@ -1847,37 +1847,37 @@
          logger.
-fatal
+error
 (%22Error reading 
@@ -1907,17 +1907,61 @@
 ion file
-%22
+: %7B%7D%22, appDefinitionResource.getDescription()
 , e);%0A  
@@ -2634,37 +2634,37 @@
          logger.
-fatal
+error
 (%22Error reading 
@@ -2687,19 +2687,20 @@
 n file: 
-%22 +
+%7B%7D%22,
  appDefi
@@ -2721,22 +2721,19 @@
 .get
-File().getPath
+Description
 (), 
@@ -3683,13 +3683,13 @@
 ger.
-fatal
+error
 (%22Er
@@ -3734,11 +3734,12 @@
 le: 
-%22 +
+%7B%7D%22,
  ext
@@ -3760,16 +3760,19 @@
 .get
-Filename
+Description
 (), 

Fix FileNotFoundException when loading file from classpath (#48)