/*
 *     Copyright (C) 2015  higherfrequencytrading.com
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.openhft.chronicle.wire;

import net.openhft.chronicle.bytes.Bytes;

import static net.openhft.chronicle.wire.Wires.toIntU30;

/**
 * Created by peter on 24/12/15.
 */
public class WriteDocumentContext implements DocumentContext {
    protected InternalWire wire;
    protected long position = -1;
    private int metaDataBit;

    public WriteDocumentContext(InternalWire wire) {
        this.wire = wire;
    }

    public void start(boolean metaData) {
        Bytes<?> bytes = wire().bytes();
        this.position = bytes.writePosition();
        metaDataBit = metaData ? Wires.META_DATA : 0;
        bytes.writeOrderedInt(metaDataBit | Wires.NOT_READY | Wires.UNKNOWN_LENGTH);
    }

    @Override
    public boolean isMetaData() {
        return metaDataBit != 0;
    }

    @Override
    public void close() {
        Bytes bytes = wire().bytes();
        long position1 = bytes.writePosition();
        if (position1 < position)
            System.out.println("Message truncated from " + position + " to " + position1);
        int length = metaDataBit | toIntU30(position1 - position - 4, "Document length %,d out of 30-bit int range.");
        if (!bytes.compareAndSwapInt(position, Wires.NOT_READY, length))
            throw new IllegalStateException("Header overwritten with " + Integer.toHexString(bytes.readInt(position)));
    }

    @Override
    public boolean isPresent() {
        return false;
    }

    @Override
    public boolean isData() {
        return metaDataBit == 0;
    }

    @Override
    public Wire wire() {
        return wire;
    }

    protected long position() {
        return position;
    }
}

@@ -1028,16 +1028,45 @@
 n = -1;%0A
+    protected int tmpHeader;%0A
     priv
@@ -1086,16 +1086,16 @@
 ataBit;%0A
-
 %0A    pub
@@ -1369,30 +1369,20 @@
     
-bytes.writeOrderedInt(
+tmpHeader = 
 meta
@@ -1429,16 +1429,57 @@
 N_LENGTH
+;%0A        bytes.writeOrderedInt(tmpHeader
 );%0A    %7D
@@ -1985,31 +1985,25 @@
 sition, 
-Wires.NOT_READY
+tmpHeader
 , length
@@ -2056,16 +2056,36 @@
 (%22Header
+ at %22 + position + %22
  overwri
@@ -2145,16 +2145,17 @@
 ion)));%0A
+%0A
     %7D%0A%0A 

Add tests for different modes of writing.