func (w *Lucene41PostingsWriter) FinishTerm(_state *BlockTermState) error {
	state := _state.Self.(*intBlockTermState)
	assert(state.DocFreq > 0)
	assert2(state.DocFreq == w.docCount, "%v vs %v", state.DocFreq, w.docCount)
	var singletonDocId int
	if state.DocFreq == 1 {
		singletonDocId = w.docDeltaBuffer[0]
	} else {
		singletonDocId = -1
		var err error
		for i := 0; i < w.docBufferUpto; i++ {
			docDelta := w.docDeltaBuffer[i]
			freq := w.freqBuffer[i]
			if !w.fieldHasFreqs {
				if err = w.docOut.WriteVInt(int32(docDelta)); err != nil {
					return err
				}
			} else if w.freqBuffer[i] == 1 {
				if err = w.docOut.WriteVInt(int32((docDelta << 1) | 1)); err != nil {
					return err
				}
			} else {
				if err = w.docOut.WriteVInt(int32(docDelta << 1)); err != nil {
					return err
				}
				if err = w.docOut.WriteVInt(int32(freq)); err != nil {
					return err
				}
			}
		}
	}
	var lastPosBlockOffset int64
	if w.fieldHasPositions {
		assert(state.TotalTermFreq != -1)
		if state.TotalTermFreq > LUCENE41_BLOCK_SIZE {
			lastPosBlockOffset = w.posOut.FilePointer() - w.posStartFP
		} else {
			lastPosBlockOffset = -1
		}
		if w.posBufferUpto > 0 {
			payloadBytesReadUpto := 0
			for i := 0; i < w.posBufferUpto; i++ {
				posDelta := w.posDeltaBuffer[i]
				if w.fieldHasPayloads {
					panic("not implemented yet")
				} else {
					err := w.posOut.WriteVInt(int32(posDelta))
					if err != nil {
						return err
					}
				}
				if w.fieldHasOffsets {
					panic("not implemented yet")
				}
			}
			if w.fieldHasPayloads {
				assert(payloadBytesReadUpto == w.payloadByteUpto)
				w.payloadByteUpto = 0
			}
		}
	} else {
		lastPosBlockOffset = -1
	}
	var skipOffset int64
	if w.docCount > LUCENE41_BLOCK_SIZE {
		n, err := w.skipWriter.WriteSkip(w.docOut)
		if err != nil {
			return err
		}
		skipOffset = n - w.docStartFP
	} else {
		skipOffset = -1
	}
	state.docStartFP = w.docStartFP
	state.posStartFP = w.posStartFP
	state.payStartFP = w.payStartFP
	state.singletonDocID = singletonDocId
	state.skipOffset = skipOffset
	state.lastPosBlockOffset = lastPosBlockOffset
	w.docBufferUpto = 0
	w.posBufferUpto = 0
	w.lastDocId = 0
	w.docCount = 0
	return nil
}
/* Called when we are done adding docs to this term
package lucene41
import (
	"errors"
	"fmt"
	"github.com/balzaczyy/golucene/core/codec"
	. "github.com/balzaczyy/golucene/core/codec/spi"
	. "github.com/balzaczyy/golucene/core/index/model"
	"github.com/balzaczyy/golucene/core/store"
	"github.com/balzaczyy/golucene/core/util"
	"github.com/balzaczyy/golucene/core/util/packed"
	"reflect"
)
const maxSkipLevels = 10
const (
	LUCENE41_TERMS_CODEC = "Lucene41PostingsWriterTerms"
	LUCENE41_DOC_CODEC   = "Lucene41PostingsWriterDoc"
	LUCENE41_POS_CODEC   = "Lucene41PostingsWriterPos"
	LUCENE41_PAY_CODEC   = "Lucene41PostingsWriterPay"
	LUCENE41_VERSION_START      = 0
	LUCENE41_VERSION_META_ARRAY = 1
	LUCENE41_VERSION_CHECKSUM   = 2
	LUCENE41_VERSION_CURRENT    = LUCENE41_VERSION_CHECKSUM
)
type Lucene41PostingsWriter struct {
	docOut store.IndexOutput
	posOut store.IndexOutput
	payOut store.IndexOutput
	lastState *intBlockTermState
	fieldHasFreqs     bool
	fieldHasPositions bool
	fieldHasOffsets   bool
	fieldHasPayloads  bool
	docStartFP int64
	posStartFP int64
	payStartFP int64
	docDeltaBuffer []int
	freqBuffer     []int
	docBufferUpto  int
	posDeltaBuffer         []int
	payloadLengthBuffer    []int
	offsetStartDeltaBuffer []int
	offsetLengthBuffer     []int
	posBufferUpto          int
	payloadBytes    []byte
	payloadByteUpto int
	lastBlockDocId           int
	lastBlockPosFP           int64
	lastBlockPayFP           int64
	lastBlockPosBufferUpto   int
	lastBlockPayloadByteUpto int
	lastDocId       int
	lastPosition    int
	lastStartOffset int
	docCount        int
	encoded []byte
	forUtil    *ForUtil
	skipWriter *SkipWriter
}
func newLucene41PostingsWriter(state *SegmentWriteState,
	accetableOverheadRatio float32) (*Lucene41PostingsWriter, error) {
	docOut, err := state.Directory.CreateOutput(
		util.SegmentFileName(state.SegmentInfo.Name,
			state.SegmentSuffix,
			LUCENE41_DOC_EXTENSION),
		state.Context)
	if err != nil {
		return nil, err
	}
	ans := new(Lucene41PostingsWriter)
	if err = func() error {
		var posOut store.IndexOutput
		var payOut store.IndexOutput
		var success = false
		defer func() {
			if !success {
				util.CloseWhileSuppressingError(docOut, posOut, payOut)
			}
		}()
		err := codec.WriteHeader(docOut, LUCENE41_DOC_CODEC, LUCENE41_VERSION_CURRENT)
		if err != nil {
			return err
		}
		ans.forUtil, err = NewForUtilInto(accetableOverheadRatio, docOut)
		if err != nil {
			return err
		}
		if state.FieldInfos.HasProx {
			ans.posDeltaBuffer = make([]int, MAX_DATA_SIZE)
			posOut, err = state.Directory.CreateOutput(util.SegmentFileName(
				state.SegmentInfo.Name, state.SegmentSuffix, LUCENE41_POS_EXTENSION),
				state.Context)
			if err != nil {
				return err
			}
			err = codec.WriteHeader(posOut, LUCENE41_POS_CODEC, LUCENE41_VERSION_CURRENT)
			if err != nil {
				return err
			}
			if state.FieldInfos.HasPayloads {
				ans.payloadBytes = make([]byte, 128)
				ans.payloadLengthBuffer = make([]int, MAX_DATA_SIZE)
			}
			if state.FieldInfos.HasOffsets {
				ans.offsetStartDeltaBuffer = make([]int, MAX_DATA_SIZE)
				ans.offsetLengthBuffer = make([]int, MAX_DATA_SIZE)
			}
			if state.FieldInfos.HasPayloads || state.FieldInfos.HasOffsets {
				payOut, err = state.Directory.CreateOutput(util.SegmentFileName(
					state.SegmentInfo.Name, state.SegmentSuffix, LUCENE41_PAY_EXTENSION),
					state.Context)
				if err != nil {
					return err
				}
				err = codec.WriteHeader(payOut, LUCENE41_PAY_CODEC, LUCENE41_VERSION_CURRENT)
			}
		}
		ans.payOut, ans.posOut = payOut, posOut
		ans.docOut = docOut
		success = true
		return nil
	}(); err != nil {
		return nil, err
	}
	ans.docDeltaBuffer = make([]int, MAX_DATA_SIZE)
	ans.freqBuffer = make([]int, MAX_DATA_SIZE)
	ans.encoded = make([]byte, MAX_ENCODED_SIZE)
	ans.skipWriter = NewSkipWriter(
		maxSkipLevels,
		LUCENE41_BLOCK_SIZE,
		state.SegmentInfo.DocCount(),
		ans.docOut,
		ans.posOut,
		ans.payOut)
	return ans, nil
}
func newLucene41PostingsWriterCompact(state *SegmentWriteState) (*Lucene41PostingsWriter, error) {
	return newLucene41PostingsWriter(state, packed.PackedInts.COMPACT)
}
type intBlockTermState struct {
	*BlockTermState
	docStartFP         int64
	posStartFP         int64
	payStartFP         int64
	skipOffset         int64
	lastPosBlockOffset int64
	singletonDocID int
}
var emptyState = newIntBlockTermState()
func newIntBlockTermState() *intBlockTermState {
	ts := &intBlockTermState{
		skipOffset:         -1,
		lastPosBlockOffset: -1,
		singletonDocID:     -1,
	}
	parent := NewBlockTermState()
	ts.BlockTermState, parent.Self = parent, ts
	return ts
}
func (ts *intBlockTermState) Clone() TermState {
	clone := newIntBlockTermState()
	clone.CopyFrom(ts)
	return clone
}
func (ts *intBlockTermState) CopyFrom(other TermState) {
	assert(other != nil)
	if ots, ok := other.(*intBlockTermState); ok {
		ts.BlockTermState.CopyFrom_(ots.BlockTermState)
		ts.docStartFP = ots.docStartFP
		ts.posStartFP = ots.posStartFP
		ts.payStartFP = ots.payStartFP
		ts.lastPosBlockOffset = ots.lastPosBlockOffset
		ts.skipOffset = ots.skipOffset
		ts.singletonDocID = ots.singletonDocID
	} else {
		panic(fmt.Sprintf("Can not copy from %v", reflect.TypeOf(other).Name()))
	}
}
func (ts *intBlockTermState) String() string {
	return fmt.Sprintf("%v docStartFP=%v posStartFP=%v payStartFP=%v lastPosBlockOffset=%v skipOffset=%v singletonDocID=%v",
		ts.BlockTermState, ts.docStartFP, ts.posStartFP, ts.payStartFP, ts.lastPosBlockOffset, ts.skipOffset, ts.singletonDocID)
}
func (w *Lucene41PostingsWriter) NewTermState() *BlockTermState {
	return newIntBlockTermState().BlockTermState
}
func (w *Lucene41PostingsWriter) Init(termsOut store.IndexOutput) error {
	err := codec.WriteHeader(termsOut, LUCENE41_TERMS_CODEC, LUCENE41_VERSION_CURRENT)
	if err == nil {
		err = termsOut.WriteVInt(LUCENE41_BLOCK_SIZE)
	}
	return err
}
func (w *Lucene41PostingsWriter) SetField(fieldInfo *FieldInfo) int {
	n := int(fieldInfo.IndexOptions())
	w.fieldHasFreqs = n >= int(INDEX_OPT_DOCS_AND_FREQS)
	w.fieldHasPositions = n >= int(INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS)
	w.fieldHasOffsets = n >= int(INDEX_OPT_DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS)
	w.fieldHasPayloads = fieldInfo.HasPayloads()
	w.skipWriter.SetField(w.fieldHasPositions, w.fieldHasOffsets, w.fieldHasPayloads)
	w.lastState = emptyState
	if w.fieldHasPositions {
		if w.fieldHasPayloads || w.fieldHasOffsets {
			return 3  
		} else {
			return 2  
		}
	} else {
		return 1  
	}
}
func (w *Lucene41PostingsWriter) StartTerm() error {
	w.docStartFP = w.docOut.FilePointer()
	if w.fieldHasPositions {
		w.posStartFP = w.posOut.FilePointer()
		if w.fieldHasPayloads || w.fieldHasOffsets {
			w.payStartFP = w.payOut.FilePointer()
		}
	}
	w.lastDocId = 0
	w.lastBlockDocId = -1
	w.skipWriter.ResetSkip()
	return nil
}
func (w *Lucene41PostingsWriter) StartDoc(docId, termDocFreq int) error {
	if w.lastBlockDocId != -1 && w.docBufferUpto == 0 {
		if err := w.skipWriter.BufferSkip(w.lastBlockDocId, w.docCount,
			w.lastBlockPosFP, w.lastBlockPayFP, w.lastBlockPosBufferUpto,
			w.lastBlockPayloadByteUpto); err != nil {
			return err
		}
	}
	docDelta := docId - w.lastDocId
	if docId < 0 || (w.docCount > 0 && docDelta <= 0) {
		return errors.New(fmt.Sprintf(
			"docs out of order (%v <= %v) (docOut : %v)",
			docId, w.lastDocId, w.docOut))
	}
	w.docDeltaBuffer[w.docBufferUpto] = docDelta
	if w.fieldHasFreqs {
		w.freqBuffer[w.docBufferUpto] = termDocFreq
	}
	w.docBufferUpto++
	w.docCount++
	if w.docBufferUpto == LUCENE41_BLOCK_SIZE {
		if err := w.forUtil.writeBlock(w.docDeltaBuffer, w.encoded, w.docOut); err != nil {
			return err
		}
		if w.fieldHasFreqs {
			if err := w.forUtil.writeBlock(w.freqBuffer, w.encoded, w.docOut); err != nil {
				return err
			}
		}
	}
	w.lastDocId = docId
	w.lastPosition = 0
	w.lastStartOffset = 0
	return nil
}
func (w *Lucene41PostingsWriter) AddPosition(position int,
	payload []byte, startOffset, endOffset int) error {
	w.posDeltaBuffer[w.posBufferUpto] = position - w.lastPosition
	if w.fieldHasPayloads {
		if len(payload) == 0 {
			w.payloadLengthBuffer[w.posBufferUpto] = 0
		} else {
			panic("not implemented yet")
		}
	}
	if w.fieldHasOffsets {
		panic("not implemented yet")
	}
	w.posBufferUpto++
	w.lastPosition = position
	if w.posBufferUpto == LUCENE41_BLOCK_SIZE {
		var err error
		if err = w.forUtil.writeBlock(w.posDeltaBuffer, w.encoded, w.posOut); err != nil {
			return err
		}
		if w.fieldHasPayloads {
			panic("niy")
		}
		if w.fieldHasOffsets {
			panic("niy")
		}
		w.posBufferUpto = 0
	}
	return nil
}
func (w *Lucene41PostingsWriter) FinishDoc() error {
	if w.docBufferUpto == LUCENE41_BLOCK_SIZE {
		w.lastBlockDocId = w.lastDocId
		if w.posOut != nil {
			if w.payOut != nil {
				w.lastBlockPayFP = w.payOut.FilePointer()
			}
			w.lastBlockPosFP = w.posOut.FilePointer()
			w.lastBlockPosBufferUpto = w.posBufferUpto
			w.lastBlockPayloadByteUpto = w.payloadByteUpto
		}
		w.docBufferUpto = 0
	}
	return nil
}