package com.infoteria.asteria.flowlibrary2.component.format;

import com.infoteria.asteria.flowengine2.EngineConstant;
import com.infoteria.asteria.flowengine2.execute.ExecuteContext;
import com.infoteria.asteria.flowengine2.flow.InputConnector;
import com.infoteria.asteria.flowlibrary2.component.ComponentException;
import com.infoteria.asteria.flowlibrary2.component.SimpleComponent;
import com.infoteria.asteria.flowlibrary2.FlowException;
import com.infoteria.asteria.flowlibrary2.property.EncodingProperty;
import com.infoteria.asteria.flowlibrary2.stream.StreamDataBinary;
import com.infoteria.asteria.flowlibrary2.stream.StreamDataObject;
import com.infoteria.asteria.flowlibrary2.stream.StreamType;

import java.io.IOException;
import java.io.File;
import java.io.ByteArrayOutputStream;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

/**
 * Zipを作成するコンポーネント
 */
public class ZipComponent extends SimpleComponent {
	
	public static final String COMPONENT_NAME = "Zip";
	public String getComponentName() { return COMPONENT_NAME;}
	public String getLicenseStr() { return EngineConstant.LICENSE_COREPLUS; }
	private EncodingProperty _filenameEncoding = new EncodingProperty("FilenameEncoding", true, true, "(System)");
	
	public ZipComponent() {
		getInputConnector().setAcceptLinkCount(InputConnector.LINK_UNBOUNDED);
		getInputConnector().setAcceptType(StreamType.ALL);
		getInputConnector().setAcceptContainer(true);
		getInputConnector().setExpandContainer(true);
		getOutputConnector().setAcceptType(StreamType.BINARY);

		registProperty(_filenameEncoding);
	}
	
	public boolean execute(ExecuteContext context) throws FlowException {
		StreamDataObject[] streams = getInputConnector().getStreamArray();
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ZipOutputStream zos = new ZipOutputStream(bos);
		String filenameEncoding = _filenameEncoding.strValue();
		if (filenameEncoding != null && filenameEncoding.length() > 0
			&& !filenameEncoding.equals("(System)")) {
			zos.setEncoding(filenameEncoding); 
		}
		try {
			try {
				int cnt = 0;
				for (int i=0; i<streams.length; i++) {
					String filename = streams[i].getFileName();
					if (filename == null)
						filename = "Asteria-Stream" + Integer.toString(++cnt) + getFileExtension(streams[i].getType());
					else
						filename = new File(filename).getName();
					byte[] data = streams[i].byteValue();
					ZipEntry entry = new ZipEntry(filename);
					entry.setSize(data.length);
					
					zos.putNextEntry(entry);
					zos.write(data);
					zos.closeEntry();
				}
				//zos.finish();
			} finally {
				zos.close();
			}
		} catch (IOException e) {
			throw new ComponentException(e);
		}
		setOutputStream(new StreamDataBinary(bos.toByteArray()));
		return true;
	}
	
	private static String getFileExtension(int type) {
		switch (type) {
			case StreamType.BINARY:
			case StreamType.FIXED_STRING:
			case StreamType.MIME:
				return ".bin";
			case StreamType.TEXT:
				return ".txt";
			case StreamType.HTML:
				return ".html";
			case StreamType.CSV:
				return ".csv";
			case StreamType.PARAMETER_LIST:
			case StreamType.RECORDS:
			case StreamType.XML:
				return ".xml";
			default:
				throw new IllegalStateException();
		}
	}
}

