package ca.ulaval.bibl.lius.index.OpenOffice;

/*
 * LIUS - Lucene Index Update and Search
 * http://sourceforge.net/projects/lius/
 *
 * Copyright (c) 2004, Laval University Library.  All rights reserved.
 *
 * This program is a free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 * 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
 * General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

import org.apache.lucene.document.Document;
import ca.ulaval.bibl.lius.config.LiusConfig;
import java.util.Collection;
import java.io.IOException;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.Enumeration;
import ca.ulaval.bibl.lius.index.XML.XmlFileIndexer;
import java.util.List;
import java.util.ArrayList;
import org.jdom.input.SAXBuilder;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import ca.ulaval.bibl.lius.config.LiusConfigBuilder;

/**
 * @author Rida Benjelloun (rida.benjelloun@bibl.ulaval.ca)
 */

public class OOIndexer
    extends XmlFileIndexer {
  private List zipFiles = new ArrayList();
  private final String TMP_UNZIP_DIR = "tmpUnzipOOForLius";
  private final Namespace NS_OO = Namespace.getNamespace("office",
      "http://openoffice.org/2000/office");
  private final Namespace NS_DC = Namespace.getNamespace("dc",
      "http://purl.org/dc/elements/1.1/");
  private final Namespace NS_OOMETA = Namespace.getNamespace("meta",
      "http://openoffice.org/2000/meta");

  public Object parse(Object file) {
    org.jdom.Document xmlDocContent = new org.jdom.Document();
    org.jdom.Document xmlMeta = new org.jdom.Document();

    try {
      List files = (List) file;
      SAXBuilder builder = new SAXBuilder();
      builder.setEntityResolver(new OpenOfficeEntityResolver());
      builder.setValidation(false);
      xmlDocContent = builder.build(new File( (String) files.get(0)));
      xmlMeta = builder.build(new File( (String) files.get(1)));
      xmlDocContent.getRootElement().addContent(xmlMeta.getRootElement().
                                                getChild("meta", NS_OO).detach());
      xmlDocContent.getRootElement().addNamespaceDeclaration(NS_DC);
      xmlDocContent.getRootElement().addNamespaceDeclaration(NS_OOMETA);
    }
    catch (JDOMException e) {
      System.out.println(e.getMessage());
    }
    catch (IOException e) {
      System.out.println(e.getMessage());
    }
    return xmlDocContent;

  }

  private List getFilesToIndex(String file) {
    String dir = (file.substring(0, ( (String) file).lastIndexOf(File.separator)));
    zipFiles = unzip( (String) file,
                     dir + File.separator + TMP_UNZIP_DIR + File.separator);
    List ls = new ArrayList();
    ls.add(0, dir + File.separator + TMP_UNZIP_DIR + File.separator +
           "content.xml");
    ls.add(1, dir + File.separator + TMP_UNZIP_DIR + File.separator +
           "meta.xml");

    return ls;
  }

  public Document createLuceneDocument(String file, LiusConfig lc) {
    Document doc = createLuceneDocument(file, lc.getOOFields());
    return doc;
  }

  public Collection getLiusFields(LiusConfig lc) {
    return lc.getOOFields();
  }

  public Collection getPopulatedCollection(Object file, Collection liusFields) {

    List toIndex = getFilesToIndex( (String) file);
    org.jdom.Document jdomDoc = (org.jdom.Document)this.parse(toIndex);
    Collection coll = super.getPopulatedCollection(jdomDoc, liusFields);
    String dir = ( ( (String) file).substring(0,
                                              ( (String) file).lastIndexOf(File.
        separator))) + File.separator + TMP_UNZIP_DIR;
    deleteDir(new File(dir));
    return coll;
  }

  public Collection getPopulatedCollection(Object file, String liusConfig) {
    LiusConfig lc = LiusConfigBuilder.getSingletonInstance().getLiusConfig(
        liusConfig);
    return getPopulatedCollection(file, lc);
  }

  public Collection getPopulatedCollection(Object file, LiusConfig lc) {
    return getPopulatedCollection(file, lc.getOOFields());
  }

  private List unzip(String zip, String destination) {
    List destLs = new ArrayList();
    Enumeration entries;
    ZipFile zipFile;
    File dest = new File(destination);
    dest.mkdir();
    if (dest.isDirectory()) {

      try {
        zipFile = new ZipFile(zip);

        entries = zipFile.entries();

        while (entries.hasMoreElements()) {
          ZipEntry entry = (ZipEntry) entries.nextElement();

          if (entry.isDirectory()) {

            (new File(dest.getAbsolutePath() + File.separator + entry.getName())).
                mkdirs();
            continue;
          }

          if (entry.getName().lastIndexOf("/") > 0) {
            File f = new File(dest.getAbsolutePath() + File.separator +
                              entry.
                              getName().substring(0,
                                                  entry.getName().lastIndexOf(
                "/")));
            f.mkdirs();
          }
          copyInputStream(zipFile.getInputStream(entry),
                          new BufferedOutputStream(new FileOutputStream(dest.
              getAbsolutePath() + File.separator +
              entry.getName())));
          destLs.add(dest.getAbsolutePath() + File.separator + TMP_UNZIP_DIR +
                     File.separator + entry.getName());
        }

        zipFile.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
    else {
      System.out.println("vous avez spécifié un fichier");
    }
    return destLs;
  }

  private void copyInputStream(InputStream in, OutputStream out) throws
      IOException {
    byte[] buffer = new byte[1024];
    int len;

    while ( (len = in.read(buffer)) >= 0)
      out.write(buffer, 0, len);

    in.close();
    out.close();
  }

  public boolean deleteDir(File dir) {
    if (dir.isDirectory()) {
      String[] children = dir.list();
      for (int i = 0; i < children.length; i++) {
        boolean success = deleteDir(new File(dir, children[i]));
        if (!success) {
          return false;
        }
      }
    }
    return dir.delete();
  }

}