/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 macromedia.abc;

import macromedia.asc.util.ByteList;
import macromedia.asc.util.ObjectList;

import java.io.IOException;
import java.io.FileOutputStream;

public class Optimizer
{
    public static void main(String[] args)
    {
        ObjectList<String> file_names = new ObjectList();
        String output_file = "merged.abc";
        for( int i = 0; i < args.length; ++i )
        {
            if( args[i].equals("-o") )
            {
                output_file = args[++i];
            }
            else
            {
                file_names.add(args[i]);
            }
        }

        BytecodeBuffer[] byte_codes = new BytecodeBuffer[file_names.size()];
        for(int i = 0; i < file_names.size(); ++i )
        {
            try
            {
                BytecodeBuffer buf = new BytecodeBuffer(file_names.at(i));
                byte_codes[i] = buf;
            }
            catch( IOException ioe )
            {

            }
        }
        byte[] abc = optimize(byte_codes);

        try
        {
            if( abc != null )
            {
                // kkiran close the FileOutputStream, else CP wont be able to
                // read the merged "abc" file
                //new FileOutputStream(output_file).write(abc);
                 FileOutputStream fos = new FileOutputStream(output_file);
                 fos.write(abc);
                 fos.close();
            }
            else
            {
                System.err.println("Error occurred when merging abc files.");
            }
        }
        catch(IOException ioe )
        {
            ioe.printStackTrace();
        }

    }

    public static ByteList optimize(ByteList bytes )
    {
        BytecodeBuffer[] byte_codes = new BytecodeBuffer[1];
        byte_codes[0] = new BytecodeBuffer(bytes.toByteArray());
        byte[] temp = optimize(byte_codes);
        ByteList new_bytes = new ByteList(temp.length);
        new_bytes.addAll(temp);
        return new_bytes;
    }

    public static byte[] optimize(BytecodeBuffer[] byte_codes)
    {
        int abcSize = byte_codes.length;
        Decoder[] decoders = new Decoder[abcSize];
        ConstantPool[] pools = new ConstantPool[abcSize];
        int majorVersion = 0, minorVersion = 0;

        boolean skipFrame = false;

        for( int j = 0; j < abcSize; ++j )
        {
            try
            {
                // ThreadLocalToolkit.logInfo(tag.name);
                decoders[j] = new Decoder(byte_codes[j]);
                if (decoders[j].majorVersion > majorVersion)
                	majorVersion = decoders[j].majorVersion;
                if (decoders[j].minorVersion > minorVersion)
                	minorVersion = decoders[j].minorVersion;
                pools[j] = decoders[j].constantPool;
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }

        }

        Encoder encoder = new Encoder(majorVersion, minorVersion);
        encoder.enablePeepHole();
        Decoder decoder = null;
        // all the constant pools are merged here...
        try
        {
            encoder.addConstantPools(pools);
            //if (!keepDebugOpcodes)
            {
                encoder.disableDebugging();
            }
            // always remove metadata...
            encoder.removeMetadata();
            encoder.configure(decoders);
        }
        catch (Throwable ex)
        {
            ex.printStackTrace();
            return null;
        }


        // decode methodInfo...
        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.MethodInfo methodInfo = decoder.methodInfo;

            try
            {
                for (int k = 0, infoSize = methodInfo.size(); k < infoSize; k++)
                {
                    methodInfo.decode(k, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        // decode metadataInfo...
        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.MetaDataInfo metadataInfo = decoder.metadataInfo;

            try
            {
                for (int k = 0, infoSize = metadataInfo.size(); k < infoSize; k++)
                {
                    metadataInfo.decode(k, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        // decode classInfo...

        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.ClassInfo classInfo = decoder.classInfo;

            try
            {
                for (int k = 0, infoSize = classInfo.size(); k < infoSize; k++)
                {
                    classInfo.decodeInstance(k, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.ClassInfo classInfo = decoder.classInfo;

            try
            {
                for (int k = 0, infoSize = classInfo.size(); k < infoSize; k++)
                {
                    classInfo.decodeClass(k, 0, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        // decode scripts...
        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.ScriptInfo scriptInfo = decoder.scriptInfo;

            try
            {
                for (int k = 0, scriptSize = scriptInfo.size(); k < scriptSize; k++)
                {
                    scriptInfo.decode(k, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        // decode method bodies...
        for (int j = 0; j < abcSize; j++)
        {
            decoder = decoders[j];
            encoder.useConstantPool(j);

            Decoder.MethodBodies methodBodies = decoder.methodBodies;

            try
            {
                for (int k = 0, bodySize = methodBodies.size(); k < bodySize; k++)
                {
                    methodBodies.decode(k, 2, encoder);
                }
            }
            catch (Throwable ex)
            {
                ex.printStackTrace();
                skipFrame = true;
                break;
            }
        }

        if (skipFrame)
        {
            return null;
        }

        byte[] abc = encoder.toABC();
        return abc;
    }
}
