/* ====================================================================
   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.hsmf.datatypes;

import java.math.BigInteger;
import java.util.Calendar;

import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;

/**
 * An instance of a {@link MAPIProperty} inside a {@link PropertiesChunk}. Where
 * the {@link Types} type is a fixed length one, this will contain the actual
 * value. Where the {@link Types} type is a variable length one, this will
 * contain the length of the property, and the value will be in the associated
 * {@link Chunk}.
 */
public class PropertyValue {
    private MAPIProperty property;
    private long flags;
    protected byte[] data;

    public PropertyValue(MAPIProperty property, long flags, byte[] data) {
        this.property = property;
        this.flags = flags;
        this.data = data;
    }

    public MAPIProperty getProperty() {
        return property;
    }

    /**
     * Get the raw value flags. TODO Also provide getters for the flag meanings
     */
    public long getFlags() {
        return flags;
    }

    public Object getValue() {
        return data;
    }

    public void setRawValue(byte[] value) {
        this.data = value;
    }

    @Override
    public String toString() {
        Object v = getValue();
        if (v == null) {
            return "(No value available)";
        }

        if (v instanceof byte[]) {
            return ByteChunk.toDebugFriendlyString((byte[]) v);
        } else {
            // Just use the normal toString on the value
            return v.toString();
        }
    }

    public static class NullPropertyValue extends PropertyValue {
        public NullPropertyValue(MAPIProperty property, long flags,
                byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Void getValue() {
            return null;
        }
    }

    public static class BooleanPropertyValue extends PropertyValue {
        public BooleanPropertyValue(MAPIProperty property, long flags,
                byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Boolean getValue() {
            short val = LittleEndian.getShort(data);
            return val > 0;
        }

        public void setValue(boolean value) {
            if (data.length != 2) {
                data = new byte[2];
            }
            if (value) {
                LittleEndian.putShort(data, 0, (short) 1);
            }
        }
    }

    public static class ShortPropertyValue extends PropertyValue {
        public ShortPropertyValue(MAPIProperty property, long flags,
                byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Short getValue() {
            return LittleEndian.getShort(data);
        }

        public void setValue(short value) {
            if (data.length != 2) {
                data = new byte[2];
            }
            LittleEndian.putShort(data, 0, value);
        }
    }

    public static class LongPropertyValue extends PropertyValue {
        public LongPropertyValue(MAPIProperty property, long flags, byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Integer getValue() {
            return LittleEndian.getInt(data);
        }

        public void setValue(int value) {
            if (data.length != 4) {
                data = new byte[4];
            }
            LittleEndian.putInt(data, 0, value);
        }
    }

    public static class LongLongPropertyValue extends PropertyValue {
        public LongLongPropertyValue(MAPIProperty property, long flags,
                byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Long getValue() {
            return LittleEndian.getLong(data);
        }

        public void setValue(long value) {
            if (data.length != 8) {
                data = new byte[8];
            }
            LittleEndian.putLong(data, 0, value);
        }
    }

    public static class FloatPropertyValue extends PropertyValue {
        public FloatPropertyValue(MAPIProperty property, long flags,
                byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Float getValue() {
            return LittleEndian.getFloat(data);
        }

        public void setValue(float value) {
            if (data.length != 4) {
                data = new byte[4];
            }
            LittleEndian.putFloat(data, 0, value);
        }
    }

    public static class DoublePropertyValue extends PropertyValue {
        public DoublePropertyValue(MAPIProperty property, long flags, byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Double getValue() {
            return LittleEndian.getDouble(data);
        }

        public void setValue(double value) {
            if (data.length != 8) {
                data = new byte[8];
            }
            LittleEndian.putDouble(data, 0, value);
        }
    }

    /**
     * signed 64-bit integer that represents a base ten decimal, with four
     * digits to the right of the decimal point
     */
    public static class CurrencyPropertyValue extends PropertyValue {
        private static final BigInteger SHIFT = BigInteger.valueOf(10000);

        public CurrencyPropertyValue(MAPIProperty property, long flags, byte[] data) {
            super(property, flags, data);
        }

        @Override
        public BigInteger getValue() {
            long unshifted = LittleEndian.getLong(data);
            return BigInteger.valueOf(unshifted).divide(SHIFT);
        }

        public void setValue(BigInteger value) {
            if (data.length != 8) {
                data = new byte[8];
            }
            long shifted = value.multiply(SHIFT).longValue();
            LittleEndian.putLong(data, 0, shifted);
        }
    }

    /**
     * 64-bit integer specifying the number of 100ns periods since Jan 1, 1601
     */
    public static class TimePropertyValue extends PropertyValue {
        private static final long OFFSET = 1000L * 60L * 60L * 24L
                * (365L * 369L + 89L);

        public TimePropertyValue(MAPIProperty property, long flags, byte[] data) {
            super(property, flags, data);
        }

        @Override
        public Calendar getValue() {
            long time = LittleEndian.getLong(data);
            time = (time / 10 / 1000) - OFFSET;

            Calendar timeC = LocaleUtil.getLocaleCalendar();
            timeC.setTimeInMillis(time);

            return timeC;
        }

        public void setValue(Calendar value) {
            if (data.length != 8) {
                data = new byte[8];
            }
            long time = value.getTimeInMillis();
            time = (time + OFFSET) * 10 * 1000;
            LittleEndian.putLong(data, 0, time);
        }
    }
}
