/*  
 * Copyright 2008 CoreMedia AG, Hamburg
 *
 * Licensed under the Apache License, Version 2.0 (the License); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an AS IS BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */

package com.coremedia.iso;

import com.coremedia.iso.boxes.AbstractContainerBox;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.MovieBox;
import com.coremedia.iso.boxes.fragment.MovieFragmentBox;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * The most upper container for ISO Boxes. It is a container box that is a file.
 * Uses IsoBufferWrapper  to access the underlying file.
 */
public class IsoFile extends AbstractContainerBox {
    protected BoxParser boxParser = new PropertyBoxParserImpl();
    protected IsoBufferWrapper originalIso;

    public IsoFile(IsoBufferWrapper originalIso) {
        super(new byte[]{});
        boxParser = createBoxParser();
        this.originalIso = originalIso;
    }

    public IsoFile(IsoBufferWrapper originalIso, BoxParser boxParser) {
        this(originalIso);
        this.boxParser = boxParser;
    }

    protected BoxParser createBoxParser() {
        return new PropertyBoxParserImpl();
    }

    @Override
    public void parse(IsoBufferWrapper in, long size, BoxParser boxParser, Box lastMovieFragmentBox) throws IOException {
        throw new RuntimeException("This method is not meant to be used. Use parse() instead");
        //super.parse(in, size, boxParser, lastMovieFragmentBox);    //To change body of overridden methods use File | Settings | File Templates.
    }

    public void parse() throws IOException {

        boolean done = false;
        Box lastMovieFragmentBox = null;
        while (!done) {
            long sp = originalIso.position();
            if (originalIso.remaining() >= 8) {
                Box box = boxParser.parseBox(originalIso, this, lastMovieFragmentBox);
                if (box != null) {
                    if (box instanceof MovieFragmentBox) lastMovieFragmentBox = box;
                    boxes.add(box);
                    assert box.calculateOffset() == sp : "calculated offset differs from offset in file";
                } else {
                    done = true;
                }
            } else {
                done = true;
            }
        }
        parsed = done;
    }


    public String toString() {
        StringBuilder buffer = new StringBuilder();
        buffer.append("IsoFile[");
        if (boxes == null) {
            buffer.append("unparsed");
        } else {
            for (int i = 0; i < boxes.size(); i++) {
                if (i > 0) {
                    buffer.append(";");
                }
                buffer.append(boxes.get(i).toString());
            }
        }
        buffer.append("]");
        return buffer.toString();
    }

    public static byte[] fourCCtoBytes(String fourCC) {
        byte[] result = new byte[4];
        if (fourCC != null) {
            for (int i = 0; i < Math.min(4, fourCC.length()); i++) {
                result[i] = (byte) fourCC.charAt(i);
            }
        }
        return result;
    }

    public static String bytesToFourCC(byte[] type) {
        byte[] result = new byte[]{0, 0, 0, 0};
        if (type != null) {
            for (int i = 0; i < Math.min(type.length, 4); i++) {
                result[i] = type[i];
            }
        }
        return new String(result, Charset.forName("ISO-8859-1"));
    }


    @Override
    public long getNumOfBytesToFirstChild() {
        return 0;
    }

    @Override
    public long getSize() {
        long size = 0;
        for (Box box : boxes) {
            size += box.getSize();
        }
        return size;
    }

    @Override
    public long calculateOffset() {
        return 0;
    }

    @Override
    public long getOffset() {
        return 0;
    }

    @Override
    public IsoFile getIsoFile() {
        return this;
    }

    @Override
    protected long getHeaderSize() {
        return 0;
    }

    @Override
    public byte[] getHeader() {
        return new byte[0];
    }

    public BoxParser getBoxParser() {
        return boxParser;
    }

    public IsoBufferWrapper getOriginalIso() {
        return originalIso;
    }

    /**
     * Shortcut to get the MovieBox since it is often needed and present in
     * nearly all ISO 14496 files (at least if they are derived from MP4 ).
     *
     * @return the MovieBox or <code>null</code>
     */
    public MovieBox getMovieBox() {
        for (Box box : boxes) {
            if (box instanceof MovieBox) {
                return (MovieBox) box;
            }
        }
        return null;
    }
}

@@ -869,27 +869,39 @@
 ava.
-n
 io.
-charset.Charset
+UnsupportedEncodingException
 ;%0A%0A/
@@ -3693,35 +3693,52 @@
         
-for (int i = 0; i %3C
+System.arraycopy(type, 0, result, 0,
  Math.mi
@@ -3754,24 +3754,18 @@
 ngth, 4)
+)
 ;
- i++) %7B
 %0A       
@@ -3761,32 +3761,34 @@
 ));%0A        
+%7D%0A
         
 result%5Bi%5D = 
@@ -3779,118 +3779,201 @@
     
-result%5Bi%5D = type%5Bi%5D;%0A            %7D%0A        %7D%0A        return new String(result, Charset.forName(%22ISO-8859-1%22));
+try %7B%0A            return new String(result, %22ISO-8859-1%22);%0A        %7D catch (UnsupportedEncodingException e) %7B%0A            throw new Error(%22Required character encoding is missing%22, e);%0A        %7D
 %0A   

make android compatible