/* 
 * $Id: ImportTextPlain.cpp,v 1.17 2006/03/05 05:00:09 ozawa Exp $
 *
 * Copyright 2005- ONGS Inc. All rights reserved.
 * 
 * author: Masanori OZAWA (ozawa@ongs.co.jp)
 * version: $Revision: 1.17 $
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY ONGS INC ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ONGS INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the ONGS Inc.
 * 
 */

#include "xdtp.h"
#include "modules/imports/ImportTextPlain.h"
#include "Utilities.h"
#include "URLTool.h"
#include "XMLTool.h"

using namespace XDTP;

ImportTextPlain::ImportTextPlain()
{
}

ImportTextPlain::~ImportTextPlain()
{
}

/**
 * XSL変換後のXML文章を保存する直前に呼び出されます。
 * 
 * @param aDocument XML文章
 */
void ImportTextPlain::treatPostDocument(xmlDocPtr aDocument)
{
    GLSDImportModuleAdapter::treatPostDocument(aDocument);

    int count;
    XMLTool tool;
    xmlNodePtr root = xmlDocGetRootElement(aDocument);
    xmlNodeSetPtr nodes;
    xmlXPathObjectPtr obj = tool.getNodeList(root, "//import[@type=\"text/plain\"]");

    if (obj) {
        nodes = obj->nodesetval;
        
        for (count = 0; count < nodes->nodeNr; count++) {
            if (!transform(aDocument, nodes->nodeTab[count])) {
                THROW("ImportTextPlain: transform failed.");
            }
        }
        
        xmlXPathFreeObject(obj);
    }
}

bool ImportTextPlain::transform(xmlDocPtr aDocument, xmlNodePtr aNode)
{
    Glib::ustring ref;
    Glib::ustring caption;
    Glib::ustring encoding;

    if (!getImportAttributes(aNode, ref, caption, encoding)) {
        return false;
    }
    
    if ("html" == m_OutputType) {
        return plainTo_nHTML(true, aDocument, aNode, ref, caption, encoding);
    }
    else if ("xhtml" == m_OutputType) {
        return plainTo_nHTML(false, aDocument, aNode, ref, caption, encoding);
    }
    else if ("text" == m_OutputType) {
        return preserveImport(aDocument, aNode, ref, caption, encoding);
    }
    // otherwise, do not operation.
    
    return true;
}

bool ImportTextPlain::plainTo_nHTML
    (bool isHTML, xmlDocPtr aDocument, xmlNodePtr aNode,
     const Glib::ustring& aRef,
     const Glib::ustring& aCaption,
     const Glib::ustring& anEncoding)
{
    // スタイルシートを取得
    xmlNodePtr comment = getStyleSheet(aDocument, "text/css");

    if (comment) {
        // スタイルシートにイメージのスタイルの指定があるか確認
        Glib::ustring content = (comment->content ? (const char*)comment->content : "");
        Glib::ustring::size_type pos = content.find("pre.plain");
        
        if (Glib::ustring::npos == pos) {
            // スタイルシートにイメージのスタイルを追加
            content += LINE_SEP;
            content += "   pre.plain {" LINE_SEP;
            content += "     text-align: left;" LINE_SEP;
            content += "     border: solid thin silver;" LINE_SEP;
            content += "     margin: 1.0em 0 0 0;" LINE_SEP;
            content += "     padding: 0.5em 1.0em 1.0em 0.5em;" LINE_SEP;
            content += "     overflow: scroll;" LINE_SEP;
            content += "   }" LINE_SEP;
            content += "   div.title {" LINE_SEP;
            content += "     text-align: center;" LINE_SEP;
            content += "     margin: 0.5em 0 1.5em 0;" LINE_SEP;
            content += "     overflow: auto;" LINE_SEP;
            content += "   }" LINE_SEP;
            xmlNodeSetContent(comment, (const xmlChar*)content.c_str());
        }
    }
    
    // ファイルを読み込み、テキストノードを構築する
    xmlNodePtr pre = xmlNewNode(NULL, (const xmlChar*)"pre");
    if (!pre) THROW("Out of memory!");
    xmlSetProp(pre, (const xmlChar*)"class", (const xmlChar*)"plain");
    xmlAddChild(pre, xmlNewText((const xmlChar*)LINE_SEP));
    
    bool bFailed = false;
    std::string tmpfile;
    try {
        Glib::RefPtr<Glib::IOChannel> ioc = getIOChannel(aRef, tmpfile);
        setEncoding(ioc, anEncoding);
        
        Glib::ustring line;
        
        while (ioc->read_line(line) == Glib::IO_STATUS_NORMAL) {
            xmlAddChild(pre, xmlNewText((const xmlChar*)line.c_str()));
        }
        ioc->close();
    }
    catch (Exception exception) {
        exception.print(stderr);
        bFailed = true;
    }
    catch (Glib::Error error) {
        std::string msg = Glib::locale_from_utf8(error.what());
        fprintf(stderr, "%s: %s (%s)" LINE_SEP, APP_NAME, msg.c_str(), aRef.c_str());
        bFailed = true;
    }
    catch (std::exception exception) {
        fprintf(stderr, "%s: %s (%s)" LINE_SEP, APP_NAME, exception.what(), aRef.c_str());
        bFailed = true;
    }
    catch (...) {
        fprintf(stderr, "%s: ImportTextPlain: unknown error occured. (%s)" LINE_SEP,
            APP_NAME, aRef.c_str());
        bFailed = true;
    }

    if (0 < tmpfile.length()) {
        remove(tmpfile.c_str());
    }
    if (bFailed) return false;

    xmlNodePtr block = xmlNewNode(NULL, (const xmlChar*)"blockquote");
    if (!block) THROW("Out of memory!");
    xmlSetProp(block, (const xmlChar*)"cite", (const xmlChar*)aRef.c_str());
    xmlAddChild(block, pre);

    xmlNodePtr title = xmlNewNode(NULL, (const xmlChar*)"div");
    if (!title) {
        xmlFreeNode(block);
        THROW("Out of memory!");
    }
    xmlSetProp(title, (const xmlChar*)"class", (const xmlChar*)"title");
    xmlAddChild(title, xmlNewText((const xmlChar*)aCaption.c_str()));
    
    xmlFreeNode(xmlReplaceNode(aNode, title));
    
    xmlAddPrevSibling(title, block);
    
    return true;
}


syntax highlighted by Code2HTML, v. 0.9.1