/*
 * 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.apache.sling.provisioning.model.io;

import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.sling.provisioning.model.Artifact;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Commentable;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.ModelConstants;
import org.apache.sling.provisioning.model.RunMode;

/**
 * This class offers a method to read a model using a {@code Reader} instance.
 */
public class ModelReader {

    private enum CATEGORY {
        NONE(null, null),
        FEATURE("feature", new String[] {"name"}),
        VARIABLES("variables", null),
        ARTIFACTS("artifacts", new String[] {"runModes", "startLevel"}),
        SETTINGS("settings", new String[] {"runModes"}),
        CONFIGURATIONS("configurations", new String[] {"runModes"}),
        CONFIG(null, null);

        public final String name;

        public final String[] parameters;

        private CATEGORY(final String n, final String[] p) {
            this.name = n;
            this.parameters = p;
        }
    }

    /**
     * Reads the model file
     * The reader is not closed. It is up to the caller to close the reader.
     *
     * @param reader The reader providing the model
     * @param location Optional location string identifying the source of the model.
     * @throws IOException If an error occurs
     */
    public static Model read(final Reader reader, final String location)
    throws IOException {
        final ModelReader mr = new ModelReader(location);
        return mr.readModel(reader);
    }

    private CATEGORY mode = CATEGORY.NONE;

    private final Model model = new Model();

    private Feature feature;
    private RunMode runMode;
    private ArtifactGroup artifactGroup;
    private Configuration config;

    private String comment;

    private StringBuilder configBuilder;

    private LineNumberReader lineNumberReader;

    private final String exceptionPrefix;

    private ModelReader(final String location) {
        this.model.setLocation(location);
        if ( location == null ) {
            exceptionPrefix = "";
        } else {
            exceptionPrefix = location + " : ";
        }
    }

    private Model readModel(final Reader reader)
    throws IOException {

        boolean global = true;

        lineNumberReader = new LineNumberReader(reader);
        String line;
        while ( (line = lineNumberReader.readLine()) != null ) {
            // trim the line
            line = line.trim();

            // ignore empty line
            if ( line.isEmpty() ) {
                checkConfig();
                continue;
            }

            // comment?
            if ( line.startsWith("#") ) {
                if ( config != null ) {
                    configBuilder.append(line);
                    configBuilder.append('\n');

                    continue;
                }
                final String c = line.substring(1).trim();
                if ( comment == null ) {
                    comment = c;
                } else {
                    comment = comment + "\n" + c;
                }
                continue;
            }

            if ( global ) {
                global = false;
                if ( !line.startsWith("[feature ") ) {
                    throw new IOException(exceptionPrefix + " Model file must start with a feature category.");
                }
            }

            if ( line.startsWith("[") ) {
                if ( !line.endsWith("]") ) {
                    throw new IOException(exceptionPrefix + "Illegal category definition in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                }
                int pos = 1;
                while ( line.charAt(pos) != ']' && !Character.isWhitespace(line.charAt(pos))) {
                    pos++;
                }
                final String category = line.substring(1, pos);
                CATEGORY found = null;
                for (CATEGORY c : CATEGORY.values()) {
                    if ( category.equals(c.name)) {
                        found = c;
                        break;
                    }
                }
                if ( found == null ) {
                    throw new IOException(exceptionPrefix + "Unknown category in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                }
                this.mode = found;
                Map<String, String> parameters = Collections.emptyMap();
                if (line.charAt(pos) != ']') {
                    final String parameterLine = line.substring(pos + 1, line.length() - 1).trim();
                    parameters = parseParameters(parameterLine, this.mode.parameters);
                }

                switch ( this.mode ) {
                    case NONE : break; // this can never happen
                    case CONFIG : break; // this can never happen
                    case FEATURE : final String name = parameters.get("name");
                                   if ( name == null ) {
                                       throw new IOException(exceptionPrefix + "Feature name missing in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                                   }
                                   if ( model.getFeature(name) != null ) {
                                       throw new IOException(exceptionPrefix + "Duplicate feature in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                                   }
                                   this.feature = model.getOrCreateFeature(name);
                                   this.init(this.feature);
                                   this.runMode = null;
                                   this.artifactGroup = null;
                                   break;
                    case VARIABLES : checkFeature();
                                     this.init(this.feature.getVariables());
                                     break;
                    case SETTINGS: checkFeature();
                                   checkRunMode(parameters);
                                   this.init(this.runMode.getSettings());
                                   break;
                    case ARTIFACTS: checkFeature();
                                    checkRunMode(parameters);
                                    int startLevel = 0;
                                    String level = parameters.get("startLevel");
                                    if ( level != null ) {
                                        try {
                                            startLevel = Integer.valueOf(level);
                                        } catch ( final NumberFormatException nfe) {
                                            throw new IOException(exceptionPrefix + "Invalid start level in line " + this.lineNumberReader.getLineNumber() + ": " + line + ":" + level);
                                        }
                                    }
                                    if ( this.runMode.getArtifactGroup(startLevel) != null ) {
                                        throw new IOException(exceptionPrefix + "Duplicate artifact group in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                                    }
                                    this.artifactGroup = this.runMode.getOrCreateArtifactGroup(startLevel);
                                    this.init(this.artifactGroup);
                                    break;
                    case CONFIGURATIONS: checkFeature();
                                         checkRunMode(parameters);
                                         this.init(this.runMode.getConfigurations());
                                         break;
                }
            } else {
                switch ( this.mode ) {
                    case NONE : break;
                    case VARIABLES : final String[] vars = parseProperty(line);
                                     feature.getVariables().put(vars[0], vars[1]);
                                     break;
                    case SETTINGS : final String[] settings = parseProperty(line);
                                    runMode.getSettings().put(settings[0], settings[1]);
                                    break;
                    case FEATURE:   this.runMode = this.feature.getOrCreateRunMode(null);
                                    this.artifactGroup = this.runMode.getOrCreateArtifactGroup(0);
                                    // no break, we continue with ARTIFACT
                    case ARTIFACTS : String artifactUrl = line;
                                     Map<String, String> parameters = Collections.emptyMap();
                                     if ( line.endsWith("]") ) {
                                         final int startPos = line.indexOf("[");
                                         if ( startPos != -1 ) {
                                             artifactUrl = line.substring(0, startPos).trim();
                                             parameters = parseParameters(line.substring(startPos + 1, line.length() - 1).trim(), null);
                                         }
                                     }
                                     try {
                                         final Artifact artifact = Artifact.fromMvnUrl("mvn:" + artifactUrl);
                                         this.init(artifact);
                                         this.artifactGroup.add(artifact);
                                         artifact.getMetadata().putAll(parameters);
                                     } catch ( final IllegalArgumentException iae) {
                                         throw new IOException(exceptionPrefix + iae.getMessage() + " in line " + this.lineNumberReader.getLineNumber(), iae);
                                     }
                                     break;
                    case CONFIGURATIONS : String configId = line;
                                          Map<String, String> cfgPars = Collections.emptyMap();
                                          if ( line.endsWith("]") ) {
                                              final int startPos = line.indexOf("[");
                                              if ( startPos != -1 ) {
                                                  configId = line.substring(0, startPos).trim();
                                                  cfgPars = parseParameters(line.substring(startPos + 1, line.length() - 1).trim(), new String[] {"format", "mode"});
                                              }
                                          }
                                          String format = cfgPars.get("format");
                                          if ( format != null ) {
                                              if ( !ModelConstants.CFG_FORMAT_FELIX_CA.equals(format)
                                                  && !ModelConstants.CFG_FORMAT_PROPERTIES.equals(format) ) {
                                                  throw new IOException(exceptionPrefix + "Unknown format configuration parameter in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                                              }
                                          } else {
                                              format = ModelConstants.CFG_FORMAT_FELIX_CA;
                                          }
                                          String cfgMode= cfgPars.get("mode");
                                          if ( cfgMode != null ) {
                                              if ( !ModelConstants.CFG_MODE_OVERWRITE.equals(cfgMode)
                                                      && !ModelConstants.CFG_MODE_MERGE.equals(cfgMode) ) {
                                                      throw new IOException(exceptionPrefix + "Unknown mode configuration parameter in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                                                  }
                                          } else {
                                              cfgMode = ModelConstants.CFG_MODE_OVERWRITE;
                                          }
                                          final String pid;
                                          final String factoryPid;
                                          final int factoryPos = configId.indexOf('-');
                                          if ( factoryPos == -1 ) {
                                              pid = configId;
                                              factoryPid = null;
                                          } else {
                                              pid = configId.substring(factoryPos + 1);
                                              factoryPid = configId.substring(0, factoryPos);
                                          }
                                          if ( runMode.getConfiguration(pid, factoryPid) != null ) {
                                              throw new IOException(exceptionPrefix + "Duplicate configuration in line " + this.lineNumberReader.getLineNumber());
                                          }
                                          config = runMode.getOrCreateConfiguration(pid, factoryPid);
                                          this.init(config);
                                          config.getProperties().put(ModelConstants.CFG_UNPROCESSED_FORMAT, format);
                                          config.getProperties().put(ModelConstants.CFG_UNPROCESSED_MODE, cfgMode);
                                          configBuilder = new StringBuilder();
                                          mode = CATEGORY.CONFIG;
                                          break;
                    case CONFIG : configBuilder.append(line);
                                  configBuilder.append('\n');
                                  break;
                }
            }

        }
        checkConfig();
        if ( comment != null ) {
            throw new IOException(exceptionPrefix + "Comment not allowed at the end of file");
        }

        return model;
    }

    /**
     * Check for a feature object
     */
    private void checkFeature() throws IOException {
        if ( feature == null ) {
            throw new IOException(exceptionPrefix + "No preceding feature definition in line " + this.lineNumberReader.getLineNumber());
        }
    }

    /**
     * Check for a run mode object
     */
    private void checkRunMode(final Map<String, String> parameters) throws IOException {
        String[] runModes = null;
        final String rmDef = parameters.get("runModes");
        if ( rmDef != null ) {
            runModes = rmDef.split(",");
            for(int i=0; i<runModes.length; i++) {
                runModes[i] = runModes[i].trim();
            }
        }
        runMode = this.feature.getOrCreateRunMode(runModes);
    }

    private void init(final Commentable traceable) {
        traceable.setComment(this.comment);
        this.comment = null;
        final String number = String.valueOf(this.lineNumberReader.getLineNumber());
        if ( model.getLocation() != null ) {
            traceable.setLocation(model.getLocation() + ":" + number);
        } else {
            traceable.setLocation(number);
        }
    }

    private void checkConfig() {
        if ( config != null ) {
            config.getProperties().put(ModelConstants.CFG_UNPROCESSED, configBuilder.toString());
            this.mode = CATEGORY.CONFIGURATIONS;
        }
        config = null;
        configBuilder = null;
    }

    /**
     * Parse a single property line
     * @param line The line
     * @return The key and the value
     * @throws IOException If something goes wrong
     */
    private String[] parseProperty(final String line) throws IOException {
        final int equalsPos = line.indexOf('=');
        final String key = line.substring(0, equalsPos).trim();
        final String value = line.substring(equalsPos + 1).trim();
        if (key.isEmpty() || value.isEmpty() ) {
            throw new IOException(exceptionPrefix + "Invalid property; " + line + " in line " + this.lineNumberReader.getLineNumber());
        }
        return new String[] {key, value};
    }

    private Map<String, String> parseParameters(final String line, final String[] allowedParameters) throws IOException {
        final Map<String, String>parameters = new HashMap<String, String>();
        final String[] keyValuePairs = line.split(" ");
        for(String kv : keyValuePairs) {
            kv = kv.trim();
            if ( !kv.isEmpty() ) {
                final int sep = kv.indexOf('=');
                if ( sep == -1 ) {
                    throw new IOException(exceptionPrefix + "Invalid parameter definition in line " + this.lineNumberReader.getLineNumber() + ": " + line);
                }
                final String key = kv.substring(0, sep).trim();
                parameters.put(key, kv.substring(sep + 1).trim());

                if ( allowedParameters != null ) {
                    boolean found = false;
                    for(final String allowed : allowedParameters) {
                        if ( key.equals(allowed) ) {
                            found = true;
                            break;
                        }
                    }
                    if ( !found ) {
                        throw new IOException(exceptionPrefix + "Invalid parameter " + key + " in line " + this.lineNumberReader.getLineNumber());
                    }
                }
            }
        }
        return parameters;
    }
}


