package org.restlet.resource;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.restlet.data.CharacterSet;
import org.restlet.data.Encoding;
import org.restlet.data.MediaType;

public class MultiPartRepresentation extends OutputRepresentation {

    private List<PartRepresentation> parts;

    private Representation source;

    /**
     * Constructor to prepare a multipart representation for generation.
     */
    public MultiPartRepresentation() {
        this(null);
    }

    /**
     * Constructor to prepare a multipart representation for parsing.
     * 
     * @param source
     *                The source representation to parse.
     */
    public MultiPartRepresentation(Representation source) {
        super(MediaType.MULTIPART_FORM_DATA);
        this.parts = new ArrayList<PartRepresentation>();
        this.source = source;

        if (source != null) {
            if (!source.getMediaType().equals(MediaType.MULTIPART_FORM_DATA)) {
                throw new IllegalArgumentException(
                        "The source representation must be of the "
                                + MediaType.MULTIPART_FORM_DATA.getName()
                                + " media type.");
            }
        }
    }

    protected PartRepresentation createPartRepresentation(String name,
            MediaType mediaType, CharacterSet characterSet,
            List<Encoding> encodings) throws IOException {
        Representation content = new InputRepresentation(this.source
                .getStream(), mediaType);
        content.setCharacterSet(characterSet);
        content.setEncodings(encodings);
        return new PartRepresentation(name, content);
    }

    public List<PartRepresentation> getParts() {
        return parts;
    }

    public void readAllParts() {
        // Potentially useful if the created part representations are not
        // transient, for example just StringRepresentation and
        // DomRepresentation instances.
    }

    public Iterator<PartRepresentation> readParts() {
        // Read the source representation for the next part
        // and updates the parts list (useful for part name, metadata)
        // PartRepresentation instance should be created via the
        // createPartRepresentation method.
        return null;
    }

    public void setParts(List<PartRepresentation> parts) {
        this.parts = parts;
    }

    @Override
    public void write(OutputStream outputStream) throws IOException {
        if (this.source == null) {
            // Write the header
            // ...

            for (PartRepresentation part : parts) {
                // Write each part
                // ...
            }

            // Write the footer
            // ...
        } else {
            if (!this.source.isTransient() && this.source.isAvailable()) {
                // The source representation doesn't come from network
                // and can apparently be directly written out
                this.source.write(outputStream);
            } else {
                // Check to see if each part representation isn't transient
                // and is available.
            }
        }
    }

}
