/*
 * blanco Framework
 * Copyright (C) 2004-2008 IGA Tosiki
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.svnconf.task;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.transform.TransformerException;

import blanco.svnconf.BlancoSvnConfConstants;
import blanco.svnconf.BlancoSvnConfMeta2Xml;
import blanco.svnconf.BlancoSvnConfXml2ApacheConfFile;
import blanco.svnconf.BlancoSvnConfXml2SvnConfFile;
import blanco.svnconf.message.BlancoSvnConfMessage;
import blanco.svnconf.task.valueobject.BlancoSvnConfProcessInput;
import blanco.svnconf.valueobject.BlancoSvnConfStructure;

public class BlancoSvnConfProcessImpl implements BlancoSvnConfProcess {
    /**
     * メッセージ。
     */
    private final BlancoSvnConfMessage fMsg = new BlancoSvnConfMessage();

    public int execute(BlancoSvnConfProcessInput input) throws IOException,
            IllegalArgumentException {
        System.out.println("- " + BlancoSvnConfConstants.PRODUCT_NAME + " ("
                + BlancoSvnConfConstants.VERSION + ")");

        try {
            final File fileMetadir = new File(input.getMetadir());
            if (fileMetadir.exists() == false) {
                throw new IllegalArgumentException(fMsg.getMbsvnca1(input
                        .getMetadir()));
            }

            // テンポラリディレクトリを作成。
            new File(input.getTmpdir()
                    + BlancoSvnConfConstants.TARGET_SUBDIRECTORY).mkdirs();

            // 指定されたメタディレクトリを処理します。
            new BlancoSvnConfMeta2Xml().processDirectory(fileMetadir, input
                    .getTmpdir()
                    + BlancoSvnConfConstants.TARGET_SUBDIRECTORY);

            final List<BlancoSvnConfStructure> listStructures = new ArrayList<BlancoSvnConfStructure>();

            // 既に存在したかどうかのチェック。
            final Map<String, BlancoSvnConfStructure> map = new HashMap<String, BlancoSvnConfStructure>();

            // XML化された中間ファイルからソースコードを生成
            final File[] fileMeta2 = new File(input.getTmpdir()
                    + BlancoSvnConfConstants.TARGET_SUBDIRECTORY).listFiles();
            for (int index = 0; index < fileMeta2.length; index++) {
                if (fileMeta2[index].getName().endsWith(".xml") == false) {
                    continue;
                }

                final BlancoSvnConfXml2SvnConfFile xml2svnConfFile = new BlancoSvnConfXml2SvnConfFile();
                xml2svnConfFile.setEncoding(input.getEncoding());
                final BlancoSvnConfStructure[] structures = xml2svnConfFile
                        .process(fileMeta2[index], new File(input
                                .getTargetdir()), input
                                .getAcceptLowerCaseUserName());
                for (int indexStructure = 0; indexStructure < structures.length; indexStructure++) {
                    listStructures.add(structures[indexStructure]);

                    // 重複チェック。
                    if (map.get(structures[indexStructure].getName()) != null) {
                        final BlancoSvnConfStructure pastStructure = (BlancoSvnConfStructure) map
                                .get(structures[indexStructure].getName());
                        throw new IllegalArgumentException(fMsg.getMbsvnc09(
                                structures[indexStructure].getName(),
                                structures[indexStructure].getDescription(),
                                pastStructure.getDescription()));
                    }
                    map.put(structures[indexStructure].getName(),
                            structures[indexStructure]);
                }
            }

            final BlancoSvnConfStructure structures[] = new BlancoSvnConfStructure[listStructures
                    .size()];
            listStructures.toArray(structures);
            final BlancoSvnConfXml2ApacheConfFile xml2apacheConfFile = new BlancoSvnConfXml2ApacheConfFile();
            xml2apacheConfFile.setEncoding(input.getEncoding());
            xml2apacheConfFile.structures2File(structures, new File(input
                    .getTargetdir()));

            return BlancoSvnConfBatchProcess.END_SUCCESS;
        } catch (TransformerException ex) {
            throw new IOException("XML変換の過程で例外が発生しました: " + ex.toString());
        }
    }
}
