/*
 * This file is part of the DITA Open Toolkit project hosted on
 * Sourceforge.net. See the accompanying license.txt file for
 * applicable licenses.
 */

/*
 * (c) Copyright IBM Corp. 2010 All Rights Reserved.
 */
package org.dita.dost.module;

import static org.dita.dost.util.Constants.*;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.dita.dost.exception.DITAOTException;
import org.dita.dost.log.DITAOTLogger;
import org.dita.dost.pipeline.AbstractPipelineInput;
import org.dita.dost.pipeline.AbstractPipelineOutput;
import org.dita.dost.reader.KeyrefReader;
import org.dita.dost.util.ListUtils;
import org.dita.dost.util.StringUtils;
import org.dita.dost.writer.KeyrefPaser;
/**
 * Keyref Module.
 *
 */
final class KeyrefModule implements AbstractPipelineModule {

    private DITAOTLogger logger;

    public void setLogger(final DITAOTLogger logger) {
        this.logger = logger;
    }

    /**
     * Entry point of KeyrefModule.
     * 
     * @param input Input parameters and resources.
     * @return null
     * @throws DITAOTException exception
     */
    public AbstractPipelineOutput execute(final AbstractPipelineInput input)
            throws DITAOTException {
        if (logger == null) {
            throw new IllegalStateException("Logger not set");
        }
        String tempDir = input.getAttribute(ANT_INVOKER_PARAM_TEMPDIR);

        //Added by William on 2010-03-30 for bug:2978858 start
        //get basedir
        final String baseDir = input.getAttribute(ANT_INVOKER_PARAM_BASEDIR);
        //Added by William on 2010-03-30 for bug:2978858 end

        if (! new File(tempDir).isAbsolute()){
            tempDir = new File(baseDir, tempDir).getAbsolutePath();
        }

        //Added by Alan Date:2009-08-04 --begin
        final String ext = input.getAttribute(ANT_INVOKER_PARAM_DITAEXT);
        final String extName = ext.startsWith(DOT) ? ext : (DOT + ext);
        //Added by Alan Date:2009-08-04 --end

        Properties properties = null;
        try{
            properties = ListUtils.getDitaList();
        }catch(final Exception e){
            logger.logException(e);
        }

        // maps of keyname and target
        final Map<String, String> keymap =new HashMap<String, String>();
        // store the key name defined in a map(keyed by ditamap file)
        final Hashtable<String, Set<String>> maps = new Hashtable<String, Set<String>>();

        // get the key definitions from the dita.list, and the ditamap where it is defined
        // are not handle yet.
        final String keylist = properties.getProperty(KEY_LIST);
        if(!StringUtils.isEmptyString(keylist)){
            final Set<String> keys = StringUtils.restoreSet(keylist);
            for(final String key: keys){
                keymap.put(key.substring(0, key.indexOf(EQUAL)),
                        key.substring(key.indexOf(EQUAL)+1, key.lastIndexOf("(")));
                // map file which define the keys
                final String map = key.substring(key.lastIndexOf("(") + 1, key.lastIndexOf(")"));
                // put the keyname into corresponding map which defines it.
                //a map file can define many keys
                if(maps.containsKey(map)){
                    maps.get(map).add(key.substring(0,key.indexOf(EQUAL)));
                }else{
                    final Set<String> set = new HashSet<String>();
                    set.add(key.substring(0, key.indexOf(EQUAL)));
                    maps.put(map, set);
                }
            }
        }
        final KeyrefReader reader = new KeyrefReader();
        reader.setLogger(logger);
        reader.setTempDir(tempDir);
        for(final String mapFile: maps.keySet()){
            logger.logInfo("Reading " + new File(tempDir, mapFile).getAbsolutePath());
            reader.setKeys(maps.get(mapFile));
            reader.read(mapFile);
        }
        final Content content = reader.getContent();
        //get files which have keyref attr
        final Set<String> parseList = StringUtils.restoreSet(properties.getProperty(KEYREF_LIST));
        //Conref Module will change file's content, it is possible that tags with @keyref are copied in
        //while keyreflist is hard update with xslt.
        //bug:3056939
        final Set<String> conrefList = StringUtils.restoreSet(properties.getProperty(CONREF_LIST));
        parseList.addAll(conrefList);
        for(final String file: parseList){
            logger.logInfo("Processing " + new File(tempDir, file).getAbsolutePath());
            final KeyrefPaser parser = new KeyrefPaser();
            parser.setLogger(logger);
            parser.setContent(content);
            parser.setTempDir(tempDir);
            parser.setKeyMap(keymap);
            //Added by Alan Date:2009-08-04
            parser.setExtName(extName);
            parser.write(file);

        }
        return null;
    }

}
