// $Id: ConvertTextInsertions.java 6811 2010-07-23 16:57:28Z nigelw $
// Copyright (c) 2010 DeltaXML Ltd. All rights reserved
/*  This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3 only,
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License version 3 for more details
    (a copy is included in the LICENSE-LGPL.txt file that accompanied this code).

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/> */
package com.deltaxml.odf.ct;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.xml.sax.InputSource;

public class ConvertTextInsertions {
  
  private final String CONTENT= "content.xml";
  private final String STYLES= "styles.xml";
  private final String META= "meta.xml";
  private final String SETTINGS= "settings.xml";
  
  public void convertFile(String path) throws Exception {
    System.out.println("Converting " + path);
    File input= new File(path);
    
    //copy the file to a temporary one
    File temp= File.createTempFile("convert", ".tmp");
    
    FileReader in = new FileReader(input);
    FileWriter out = new FileWriter(temp);
    int c;

    while ((c = in.read()) != -1) {
      out.write(c);
    }

    in.close();
    out.close();
    
    //now convert the temp file, using the original input as the result file
    ZipFile zip= new ZipFile(temp);
    
    InputStream content= zip.getInputStream(zip.getEntry(CONTENT));
    InputStream styles= zip.getInputStream(zip.getEntry(STYLES));
    InputStream meta= zip.getInputStream(zip.getEntry(META));
    InputStream settings= zip.getInputStream(zip.getEntry(SETTINGS));
    
    InputSource contentSrc= new InputSource(content);
    contentSrc.setSystemId(temp.toURI().toString());
    
    InputSource stylesSrc= new InputSource(styles);
    stylesSrc.setSystemId(temp.toURI().toString());
    
    InputSource metaSrc= new InputSource(meta);
    metaSrc.setSystemId(temp.toURI().toString());
    
    InputSource settingsSrc= new InputSource(settings);
    settingsSrc.setSystemId(temp.toURI().toString());
    
    ZipOutputStream resultZip= new ZipOutputStream(new FileOutputStream(input));
    copyZipEntries(zip, resultZip, new String [] {CONTENT, STYLES, META, SETTINGS});
    
    resultZip.putNextEntry(new ZipEntry(CONTENT));
    convertSource(contentSrc, resultZip);
    resultZip.closeEntry();
    
    resultZip.putNextEntry(new ZipEntry(STYLES));
    convertSource(stylesSrc, resultZip);
    resultZip.closeEntry();
    
    resultZip.putNextEntry(new ZipEntry(META));
    convertSource(metaSrc, resultZip);
    resultZip.closeEntry();
    
    resultZip.putNextEntry(new ZipEntry(SETTINGS));
    convertSource(settingsSrc, resultZip);
    resultZip.closeEntry();
    
    resultZip.close();
    
  }
  
  private final String CONVERT= "xsl/convert-text-insertions.xsl";
  
  TransformerFactory tf= TransformerFactory.newInstance();
  
  private void convertSource(InputSource in, OutputStream out) throws Exception {
    Transformer t= tf.newTransformer(new StreamSource(this.getClass().getClassLoader().getResourceAsStream(CONVERT)));
    t.setURIResolver(new OdtUriResolver());
    t.transform(new SAXSource(in), new StreamResult(out));
  }
  
  private void copyZipEntries(ZipFile inputZip, ZipOutputStream resultZip, String[] exclusions) throws Exception {
    List<String> excludeList= new ArrayList<String>();
    for (String s: exclusions) {
      excludeList.add(s);
    }
    
    Enumeration<? extends ZipEntry> docEntries= inputZip.entries();
    
    while (docEntries.hasMoreElements()) {
      ZipEntry entry= docEntries.nextElement();
      if (!excludeList.contains(entry.getName())) {
        InputStream in;
        in= inputZip.getInputStream(entry);
        resultZip.putNextEntry(entry);
        writeEntry(in, resultZip);
      }
    }
  }
  
  private void writeEntry(InputStream in, ZipOutputStream out) throws Exception {
    byte[] buf= new byte[1024];
    // Transfer bytes from the file to the ZIP file
    int len;
    while ((len= in.read(buf)) > 0) {
      out.write(buf, 0, len);
    }
    
    // Complete the entry
    out.closeEntry();
    in.close();
  }
  
  public static void main(String[] args) throws Exception {
    
    ConvertTextInsertions cti= new ConvertTextInsertions();
    
    for (String s: args) {
      cti.convertFile(s);
    }
    
  }
  
}
