/**************************************************************************
 OmegaT - Computer Assisted Translation (CAT) tool
          with fuzzy matching, translation memory, keyword search,
          glossaries, and translation leveraging into updated projects.

 Copyright (C) 2017 Thomas Cordonnier
               Home page: http://www.omegat.org/
               Support center: http://groups.yahoo.com/group/OmegaT/

 This file is part of OmegaT.

 OmegaT is 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 3 of the License, or
 (at your option) any later version.

 OmegaT 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, see <http://www.gnu.org/licenses/>.
 **************************************************************************/

package org.omegat.filters4;

import java.io.*;
import java.util.Enumeration;
import java.util.zip.*;
import java.util.regex.*;

import org.omegat.core.Core;
import org.omegat.filters2.AbstractFilter;
import org.omegat.filters2.FilterContext;
import org.omegat.filters2.TranslationException;
import org.omegat.filters4.xml.AbstractXmlFilter;
import org.omegat.util.xml.XMLReader;

/**
 * Filter for a file format which is an archive containing XML
 *
 * @author Thomas Cordonnier
 */
public abstract class AbstractZipFilter extends AbstractFilter {
    
    @Override public boolean isSourceEncodingVariable() { return true; }
    @Override public boolean isTargetEncodingVariable() { return true; }

    /** Indicate that this file contained in the archive should be considered **/
    protected abstract boolean acceptEntry (ZipEntry entry, FilterContext context);
    
    @Override
    public boolean isFileSupported(java.io.File inFile, java.util.Map<String, String> config, FilterContext context) {
        try {
            ZipFile file = new ZipFile(inFile);
            Enumeration<? extends ZipEntry> entries = file.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (acceptEntry(entry, context)) {
                    file.close();
                    return true;
                }
            }
            file.close();
        } catch (IOException e) {
        }
        return false;
    }

    /** Indicate that this file contained in the archive should be translated **/
    protected abstract boolean mustTranslateEntry (ZipEntry entry, FilterContext context);
    
    protected abstract AbstractXmlFilter getFilter (ZipEntry ze);
    
    /** Processes a ZIP file. */
    @Override
    public void processFile(File inFile, File outFile, FilterContext fc) throws IOException, TranslationException {        
        ZipFile zf = new ZipFile(inFile);
        ZipOutputStream zipout = null;
        if (outFile != null)
            zipout = new ZipOutputStream(new FileOutputStream(outFile));

        Enumeration<? extends ZipEntry> zipcontents = zf.entries();
        while (zipcontents.hasMoreElements()) {
            ZipEntry ze = zipcontents.nextElement();
            if (mustTranslateEntry(ze, fc)) {
                AbstractXmlFilter xmlfilter = getFilter(ze);
                XMLReader xReader = new XMLReader(zf.getInputStream (ze));
                BufferedReader reader = new BufferedReader(xReader);  
                if (zipout == null) xmlfilter.processFile (reader, null, fc);
                else {
                    ZipEntry outEntry = new ZipEntry(ze.getName()); zipout.putNextEntry(outEntry);
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter (zipout, xReader.getEncoding()));
                    xmlfilter.processFile (reader, writer, fc);
                    zipout.closeEntry();
                }
            } else {
                if (zipout != null) {
                    ZipEntry outEntry = new ZipEntry(ze.getName());
                    zipout.putNextEntry(outEntry);

                    org.apache.commons.io.IOUtils.copy(zf.getInputStream(ze), zipout);
                    zipout.closeEntry();
                }
            }
        }
        if (zipout != null) zipout.close();
        zf.close();
    }
    
    protected void processFile(BufferedReader inFile, BufferedWriter outFile, FilterContext fc) throws IOException, TranslationException {
        throw new IOException("Not implemented");
    }
    
}
