/* ====================================================================
   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 org.apache.poi.hpsf;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianConsts;

/**
 * Supports reading and writing of variant data.<p>
 *
 * <strong>FIXME (3):</strong> Reading and writing should be made more
 * uniform than it is now. The following items should be resolved:
 *
 * <ul>
 *
 * <li>Reading requires a length parameter that is 4 byte greater than the
 * actual data, because the variant type field is included.
 *
 * <li>Reading reads from a byte array while writing writes to an byte array
 * output stream.
 *
 * </ul>
 */
public class VariantSupport extends Variant {
    /**
     * HPSF is able to read these {@link Variant} types.
     */
    public static final int[] SUPPORTED_TYPES = { Variant.VT_EMPTY,
            Variant.VT_I2, Variant.VT_I4, Variant.VT_I8, Variant.VT_R8,
            Variant.VT_FILETIME, Variant.VT_LPSTR, Variant.VT_LPWSTR,
            Variant.VT_CF, Variant.VT_BOOL };


    private static final Logger LOG = LogManager.getLogger(VariantSupport.class);
    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000;

    private static boolean logUnsupportedTypes;

    /**
     * Keeps a list of the variant types an "unsupported" message has already
     * been issued for.
     */
    private static List<Long> unsupportedMessage;

    private static final byte[] paddingBytes = new byte[3];


    /**
     * Specifies whether warnings about unsupported variant types are to be
     * written to {@code System.err} or not.
     *
     * @param logUnsupportedTypes If {@code true} warnings will be written,
     * if {@code false} they won't.
     */
    public static void setLogUnsupportedTypes(final boolean logUnsupportedTypes) {
        VariantSupport.logUnsupportedTypes = logUnsupportedTypes;
    }

    /**
     * Checks whether logging of unsupported variant types warning is turned
     * on or off.
     *
     * @return {@code true} if logging is turned on, else
     * {@code false}.
     */
    public static boolean isLogUnsupportedTypes() {
        return logUnsupportedTypes;
    }



    /**
     * Writes a warning to {@code System.err} that a variant type is
     * unsupported by HPSF. Such a warning is written only once for each variant
     * type. Log messages can be turned on or off by
     *
     * @param ex The exception to log
     */
    protected static void writeUnsupportedTypeMessage
        (final UnsupportedVariantTypeException ex) {
        if (isLogUnsupportedTypes())
        {
            if (unsupportedMessage == null) {
                unsupportedMessage = new LinkedList<>();
            }
            Long vt = Long.valueOf(ex.getVariantType());
            if (!unsupportedMessage.contains(vt))
            {
            	LOG.atError().withThrowable(ex).log("Unsupported type");
                unsupportedMessage.add(vt);
            }
        }
    }



    /**
     * Checks whether HPSF supports the specified variant type. Unsupported
     * types should be implemented included in the {@link #SUPPORTED_TYPES}
     * array.
     *
     * @see Variant
     * @param variantType the variant type to check
     * @return {@code true} if HPFS supports this type, else
     *         {@code false}
     */
    public boolean isSupportedType(final int variantType) {
        for (int st : SUPPORTED_TYPES) {
            if (variantType == st) {
                return true;
            }
        }
        return false;
    }



    /**
     * Reads a variant type from a byte array.
     *
     * @param src The byte array
     * @param offset The offset in the byte array where the variant starts
     * @param length The length of the variant including the variant type field
     * @param type The variant type to read
     * @param codepage The codepage to use for non-wide strings
     * @return A Java object that corresponds best to the variant field. For
     *         example, a VT_I4 is returned as a {@link Long}, a VT_LPSTR as a
     *         {@link String}.
     * @exception ReadingNotSupportedException if a property is to be written
     *            who's variant type HPSF does not yet support
     * @exception UnsupportedEncodingException if the specified codepage is not
     *            supported.
     * @see Variant
     */
    public static Object read( final byte[] src, final int offset,
            final int length, final long type, final int codepage )
    throws ReadingNotSupportedException, UnsupportedEncodingException {
        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(src, offset);
        return read( lei, length, type, codepage );
    }

    public static Object read( LittleEndianByteArrayInputStream lei,
            final int length, final long type, final int codepage )
    throws ReadingNotSupportedException, UnsupportedEncodingException {
        final int offset = lei.getReadIndex();
        TypedPropertyValue typedPropertyValue = new TypedPropertyValue( (int) type, null );
        try {
            typedPropertyValue.readValue(lei);
        } catch ( UnsupportedOperationException exc ) {
            try {
                final byte[] v = IOUtils.toByteArray(lei, length, MAX_RECORD_LENGTH);
                throw new ReadingNotSupportedException( type, v );
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        switch ( (int) type ) {
            /*
             * we have more property types that can be converted into Java
             * objects, but current API need to be preserved, and it returns
             * other types as byte arrays. In future major versions it shall be
             * changed -- sergey
             */
            case Variant.VT_EMPTY:
            case Variant.VT_I1:
            case Variant.VT_UI1:
            case Variant.VT_UI2:
            case Variant.VT_I4:
            case Variant.VT_UI4:
            case Variant.VT_I8:
            case Variant.VT_UI8:
            case Variant.VT_R4:
            case Variant.VT_R8:
                return typedPropertyValue.getValue();

            /*
             * also for backward-compatibility with prev. versions of POI
             * --sergey
             */
            case Variant.VT_I2:
                return ( (Short) typedPropertyValue.getValue() ).intValue();

            case Variant.VT_FILETIME:
                Filetime filetime = (Filetime) typedPropertyValue.getValue();
                return filetime.getJavaValue();

            case Variant.VT_LPSTR:
                CodePageString cpString = (CodePageString) typedPropertyValue.getValue();
                return cpString.getJavaValue( codepage );

            case Variant.VT_LPWSTR:
                UnicodeString uniString = (UnicodeString) typedPropertyValue.getValue();
                return uniString.toJavaString();

            // if(l1 < 0) {
            /*
             * YK: reading the ClipboardData packet (VT_CF) is not quite
             * correct. The size of the data is determined by the first four
             * bytes of the packet while the current implementation calculates
             * it in the Section constructor. Test files in Bugzilla 42726 and
             * 45583 clearly show that this approach does not always work. The
             * workaround below attempts to gracefully handle such cases instead
             * of throwing exceptions.
             *
             * August 20, 2009
             */
            // l1 = LittleEndian.getInt(src, o1); o1 += LittleEndianConts.INT_SIZE;
            // }
            // final byte[] v = new byte[l1];
            // System.arraycopy(src, o1, v, 0, v.length);
            // value = v;
            // break;
            case Variant.VT_CF:
                ClipboardData clipboardData = (ClipboardData) typedPropertyValue.getValue();
                return clipboardData.toByteArray();

            case Variant.VT_BOOL:
                VariantBool bool = (VariantBool) typedPropertyValue.getValue();
                return bool.getValue();

            /*
             * it is not very good, but what can do without breaking current
             * API? --sergey
             */
            default:
                final int unpadded = lei.getReadIndex()-offset;
                lei.setReadIndex(offset);
                final byte[] v = IOUtils.safelyAllocate(unpadded, MAX_RECORD_LENGTH);
                lei.readFully( v, 0, unpadded );
                throw new ReadingNotSupportedException( type, v );
        }
    }

    /**
     * Writes a variant value to an output stream. This method ensures that
     * always a multiple of 4 bytes is written.<p>
     *
     * @param out The stream to write the value to.
     * @param type The variant's type.
     * @param value The variant's value.
     * @param codepage The codepage to use to write non-wide strings
     * @return The number of entities that have been written. In many cases an
     * "entity" is a byte but this is not always the case.
     * @exception IOException if an I/O exceptions occurs
     * @exception WritingNotSupportedException if a property is to be written
     * who's variant type HPSF does not yet support
     */
    public static int write(final OutputStream out, final long type,
                            final Object value, final int codepage)
    throws IOException, WritingNotSupportedException {
        int length = -1;
        switch ((int) type) {
            case Variant.VT_BOOL: {
                if (value instanceof Boolean) {
                    int bb = ((Boolean)value) ? 0xff : 0x00;
                    out.write(bb);
                    out.write(bb);
                    length = 2;
                }
                break;
            }

            case Variant.VT_LPSTR:
                if (value instanceof String) {
                    CodePageString codePageString = new CodePageString();
                    codePageString.setJavaValue( (String)value, codepage );
                    length = codePageString.write( out );
                }
                break;

            case Variant.VT_LPWSTR:
                if (value instanceof String) {
                    UnicodeString uniString = new UnicodeString();
                    uniString.setJavaValue((String)value);
                    length = uniString.write(out);
                }
                break;

            case Variant.VT_CF:
                if (value instanceof byte[]) {
                    final byte[] cf = (byte[]) value;
                    out.write(cf);
                    length = cf.length;
                }
                break;

            case Variant.VT_EMPTY:
                LittleEndian.putUInt(Variant.VT_EMPTY, out);
                length = LittleEndianConsts.INT_SIZE;
                break;

            case Variant.VT_I2:
                if (value instanceof Number) {
                    LittleEndian.putShort( out, ((Number)value).shortValue() );
                    length = LittleEndianConsts.SHORT_SIZE;
                }
                break;

            case Variant.VT_UI2:
                if (value instanceof Number) {
                    LittleEndian.putUShort( ((Number)value).intValue(), out );
                    length = LittleEndianConsts.SHORT_SIZE;
                }
                break;

            case Variant.VT_I4:
                if (value instanceof Number) {
                    LittleEndian.putInt( ((Number)value).intValue(), out);
                    length = LittleEndianConsts.INT_SIZE;
                }
                break;

            case Variant.VT_UI4:
                if (value instanceof Number) {
                    LittleEndian.putUInt( ((Number)value).longValue(), out);
                    length = LittleEndianConsts.INT_SIZE;
                }
                break;

            case Variant.VT_I8:
                if (value instanceof Number) {
                    LittleEndian.putLong( ((Number)value).longValue(), out);
                    length = LittleEndianConsts.LONG_SIZE;
                }
                break;

            case Variant.VT_UI8: {
                if (value instanceof Number) {
                    BigInteger bi = (value instanceof BigInteger) ? (BigInteger)value : BigInteger.valueOf(((Number)value).longValue());
                    if (bi.bitLength() > 64) {
                        throw new WritingNotSupportedException(type, value);
                    }

                    byte[] biBytesBE = bi.toByteArray(), biBytesLE = new byte[LittleEndianConsts.LONG_SIZE];
                    int i=biBytesBE.length;
                    for (byte b : biBytesBE) {
                        if (i<=LittleEndianConsts.LONG_SIZE) {
                            biBytesLE[i-1] = b;
                        }
                        i--;
                    }

                    out.write(biBytesLE);
                    length = LittleEndianConsts.LONG_SIZE;
                }
                break;
            }

            case Variant.VT_R4: {
                if (value instanceof Number) {
                    int floatBits = Float.floatToIntBits(((Number)value).floatValue());
                    LittleEndian.putInt(floatBits, out);
                    length = LittleEndianConsts.INT_SIZE;
                }
                break;
            }

            case Variant.VT_R8:
                if (value instanceof Number) {
                    LittleEndian.putDouble( ((Number)value).doubleValue(), out);
                    length = LittleEndianConsts.DOUBLE_SIZE;
                }
                break;

            case Variant.VT_FILETIME:
                Filetime filetimeValue = (value instanceof Date) ? new Filetime((Date)value) : new Filetime();
                length = filetimeValue.write( out );
                break;

            default:
                break;
        }

        /* The variant type is not supported yet. However, if the value
         * is a byte array we can write it nevertheless. */
        if (length == -1) {
            if (value instanceof byte[]) {
                final byte[] b = (byte[]) value;
                out.write(b);
                length = b.length;
                writeUnsupportedTypeMessage(new WritingNotSupportedException(type, value));
            } else {
                throw new WritingNotSupportedException(type, value);
            }
        }

        /* pad values to 4-bytes */
        int padding = (4-(length & 0x3)) & 0x3;
        out.write(paddingBytes, 0, padding);

        return length + padding;
    }
}
