/*
 * @(#)GeneratePage.java
 *
 * RID-X    : 製作指示書／紙芝居のページ生成
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2002/10/01
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 */
package jp.co.nri.rid.generator;

import java.io.*;
import java.util.*;
import org.w3c.dom.*;

import jp.co.nri.Ridual;
import jp.co.nri.rid.mapper.*;
import jp.co.nri.rid.error.*;
import jp.co.nri.rid.snapshot.xcopy;

import jp.co.iti.fagot.ZApp;
import jp.co.iti.fagot.doc.DocDocument;
import jp.co.iti.fagot.doc.DocManager;
import jp.co.iti.fagot.util.ZDebug;
import jp.co.iti.fagot.util.ZResource;
import jp.co.iti.fagot.util.ZProperties;
import jp.co.iti.fagot.util.ZString;


/**
 * Rid 製作指示書／紙芝居のページ生成
 */
public class GeneratePage extends GenerateParser {
    /** RCS ID */
    private static final String RCSID =
        "$Id: GeneratePage.java,v 1.3 2003/01/24 15:19:29 nsmr Exp $";

    /** rid.template.dirプロパティ  **/
    final static public String RID_TEMPLATE_DIR = "rid.template.dir";
    /** rid.parts.dirプロパティ  **/
    final static public String RID_PARTS_DIR    = "rid.parts.dir";
    /** rid.html.dirプロパティ  **/
//    final static public String RID_HTML_DIR     = "rid.html.dir";

    /** ＨＴＭＬファイルのディレクトリ  **/
    private static String pr_htmlDir;
    /** テンプレートファイル（project）のディレクトリ  **/
    private static String pr_templateDir;
    /** テンプレートファイル（Parts）のディレクトリ  **/
    private static String pr_partsDir;


/**
  * デフォルトコンストラクタ
  */
    public GeneratePage() {
        pr_htmlDir = "";                    // ＨＴＭＬファイルのディレクトリ
        pr_templateDir = "";                // テンプレートファイル（project）のディレクトリ
        pr_partsDir = "";                   // テンプレートファイル（Parts）のディレクトリ
    }


/**
  * ページ生成
  *
  * @param  Document    doc             ドキュメント
  * @param  String      project_dir     プロジェクトディレクトリ
  * @return boolean     true(成功)/false(失敗)
  */
    public boolean generate(Document doc, String project_dir) throws RidException, Exception {

        boolean ret = false;
        RidMessage ridMsg = new RidMessage();

        //ディレクトリの取得
        ZResource res = ZApp.getTheApp().getResource();
//        pr_htmlDir     = project_dir + File.separator + res.getString(RID_HTML_DIR);       // htmlディレクトリ
        pr_htmlDir     = Ridual.getHtmlDir();       // htmlディレクトリ
        pr_templateDir = project_dir + File.separator + res.getString(RID_TEMPLATE_DIR);   // テンプレートディレクトリ
        pr_partsDir    = project_dir + File.separator + res.getString(RID_PARTS_DIR);      // テンプレートディレクトリ

        //documentの解析
        ProjectInfo  project_info = new ProjectInfo();
        project_info = documentParser(doc, "", "");

        //ページの生成
        ret = pageZone(project_info.zone, null);

        return ret;
    }

/**
  * ページ生成　（ZONE)
  *
  * @param  ZoneInfo    zone            Zone情報
  * @param  ZoneInfo    parent          Zone情報の親
  * @return boolean     true（成功）/ false（失敗）
  */
    private boolean pageZone(ZoneInfo zone, ZoneInfo parent) throws Exception {

        boolean ret = true;
        xcopy xc = new xcopy();

        // Topゾーン以外の時 2002.10.01
        // 空のゾーンでも、ディレクトリを作成する
        if (!zone.top) {
            // ディレクトリパス取得し、生成
            String dir_name = web2SeparatorChar(pr_htmlDir + File.separator + zone.file);
            ret = xc.makeDir(dir_name);

            /* ディレクトリの生成に成功した場合、Exist アトリビュートを true
             * にする。
             * t3-nishimura@nri
             */
            if (xc.fileExists(dir_name)) {
                zone.element.attribute("Exist", "true");
            }
        }

        // ディレクトリの生成に成功した場合のみ
        if (ret){
            //Page情報
            if (zone.page_lst.size() > 0) {
                //Zoneにページが存在する
                for ( int i = 0; i < zone.page_lst.size(); i++ ) {
                    PageInfo page_info = (PageInfo)zone.page_lst.elementAt(i);
                    ret = generatePage(zone, page_info);
                    //if (!ret) return false;　edit 2002.10.01
                }
            }
            //Zone情報
            for ( int n = 0; n < zone.zone_lst.size(); n++ ) {
                ZoneInfo zone_info = (ZoneInfo)zone.zone_lst.elementAt(n);
                ret = pageZone(zone_info, zone);  
                //if (!ret) return false;     edit 2002.10.01
            }
        }
        return ret;
    }



/**
  * ページの生成
  *
  * @param  PageInfo    page_info       ページ情報
  * @return boolean true(成功) / false (失敗)
  */
    private boolean generatePage(ZoneInfo zone, PageInfo page) throws RidException, Exception {

        boolean ret = true;
        xcopy xc = new xcopy();
        RidMessage ridMsg = new RidMessage();

        //ファイルの存在確認
        String out = web2SeparatorChar(pr_htmlDir + File.separator + page.file);
        if (!xc.fileExists(out)) {

            // ディレクトリパス取得し、存在チェックを行う edit 2002.10.01
            String dir_name = out.substring(0, out.lastIndexOf(File.separatorChar));
            if (xc.fileExists(dir_name)){
                // Templateファイル名を取得する
                String template = getPageTemplate(zone);
            
                //データの生成
                Document data = generatePageData(page);

                // HTMLの生成　Mapper {template + date ==> out} 
                Mapper mapper = new Mapper();
                ret = mapper.Type2(template, data, out);
                if(!ret)  ZDebug.trace(ridMsg.Warning("W4001", out));

                //テンポラリのテンプレートファイルの場合削除
                if (template.indexOf(puTemplPage) == -1) {
                    File  fTemp = new File(template);
                    fTemp.delete();
                }

                /* ファイルの生成に成功した場合、Exist アトリビュートを true
                 * にする。
                 *  t3-nishimura@nri
                 */
                if (xc.fileExists(out)) {
                    page.element.attribute("Exist", "true");
                }
            }
        }
        return ret;
    }

/**
  * Web系の区切り文字「／」をシステムデフォルトに変換する
  *
  * @param  String      file            文字列
  * @return 変換後の文字列
  */
    public String web2SeparatorChar(String file) {
        return file.replace('/', File.separatorChar);
    }

/**
  * データデータの生成
  *
  * @param  PageInfo    page            ページ情報
  * @return void
  *
  * <RidProject>
  *   <属性名>属性値</属性名>
  *   ...
  * </RidProject>
  */
    private Document generatePageData(PageInfo page) throws RidException, Exception {

        XmlUtil xu = new XmlUtil();

        // Document生成
        Document doc = new org.apache.xerces.dom.DocumentImpl();
        Element topElem = doc.createElement(puRootTag);
        doc.appendChild(topElem);

        // PageUnitの全属性を出力
        for ( int i = 0; i < page.attr_lst.size(); i++ ) {
            Attribute attr = (Attribute)page.attr_lst.elementAt(i);
            xu.createOrSetTextValue(topElem, attr.name, attr.value);
        }

        //<Rid_Progress>タグの出力

        // Rid_Progressの属性一覧を取得
        ZProperties prop  = DocManager.loadProperty( DocManager.ELEMENT );
        String[] attrs = ZString.tokenize(prop.getProperty("RidProgress.attributes"));
        String ridProgress;
        String attrName;
        String attrValue;

        
        // 属性名を取得
        ridProgress = "<rid_progress";
        for (int n = 0 ; n < attrs.length ; n++) {
            attrName = attrs[n];
            attrValue = "";
            for ( int i = 0; i < page.attr_lst.size(); i++ ) {
                Attribute attr = (Attribute)page.attr_lst.elementAt(i);

                if (attrName.compareTo(attr.name) == 0) {
                    attrValue = attr.value;
                    break;
                }
            }
            ridProgress = ridProgress + " " + attrName.toLowerCase() + "=\"" + attrValue + "\"";
        }
        ridProgress = ridProgress + ">";

        xu.createOrSetTextValue(topElem, "RidProgress", ridProgress);
        return doc;
    }


/**
  * ページのテンプレートファイル取得
  *
  * Zone属性の[template1]/[template2]に指定されている
　* テンプレートファイルを足してテンプレートファイルとする
　* 但し、 [template1]/[template2]が指定されてない場合はデフォルトの_page.htmlとする
  * @param  ZoneInfo    zone            ページ情報
  * @return String      テンプレートファイル名
  */
    private String getPageTemplate(ZoneInfo zone) throws RidException, Exception {

        String template;
        xcopy xc = new xcopy();
        RidMessage ridMsg = new RidMessage();

        // template1/2が指定されてない場合は、デフォルトの_page.htmlを使用する
        if (isNullString(zone.template1) && isNullString(zone.template2)) {
            //template1とtemplate2が設定されてない場合
            template = pr_templateDir + File.separator + puTemplPage;
        } else {
            //テンポラリーファイルを生成し、処理が終了時に削除する
            File tempf = File.createTempFile("_ridTmp",null, new File(pr_partsDir));
            template = tempf.getAbsolutePath();

            //ファイルオープン
            FileOutputStream outFileStream = new FileOutputStream(template);
            OutputStreamWriter outWriter = new OutputStreamWriter(outFileStream);

            //テンプレート１
            if (!isNullString(zone.template1)){
                String temp1 = pr_partsDir + File.separator + zone.template1;
                //ファイルの存在確認
                if(xc.fileExists(temp1)) {
                    String temp1String = file2String(temp1);
                    outWriter.write(temp1String, 0, temp1String.length());
                } else {
                    ZDebug.trace(ridMsg.Warning("W4002",temp1));
                }
           }

            //テンプレート２
            if (!isNullString(zone.template2)){
                String temp2 = pr_partsDir + File.separator + zone.template2;
                //ファイルの存在確認
                if(xc.fileExists(temp2)) {
                    String temp2String = file2String(temp2);
                    outWriter.write(temp2String, 0, temp2String.length());
                } else {
                    ZDebug.trace(ridMsg.Warning("W4002",temp2));
                }
            }
            outWriter.close();
        }
        return template;
    }


/**
  * ファイルの内容を１バイト毎読み、String型に変換する
  *
  * @param  String      file_name       ファイル名
  * @return String      ファイルの内容
  */
    private String file2String(String file_name) throws RidException, IOException {

        String fileString = "";
        char str[]=new char[256];

        try{
            FileInputStream inFileStream = new FileInputStream(file_name);
            InputStreamReader InData=new InputStreamReader(inFileStream);
            while ((InData.read(str, 0, 1)) != -1) {
                fileString = fileString + str[0];
            }
            InData.close();
        }
        catch(IOException e){
            throw new RidException(e.getMessage());
        }
        return fileString;
   }

}
