/*
 * Copyright 2017 HugeGraph Authors
 *
 * 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 com.baidu.hugegraph.computer.core.store.file.seqfile;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;

import com.baidu.hugegraph.computer.core.common.Constants;
import com.baidu.hugegraph.computer.core.config.ComputerOptions;
import com.baidu.hugegraph.computer.core.config.Config;
import com.baidu.hugegraph.computer.core.io.AbstractBufferedFileOutput;
import com.baidu.hugegraph.util.E;

public class ValueFileOutput extends AbstractBufferedFileOutput {

    private final long maxSegmentSize;
    private final File dir;
    private final List<File> segments;

    private int segmentIndex;
    private RandomAccessFile currentSegment;

    public ValueFileOutput(Config config, File dir) throws IOException {
        this(config, dir, Constants.BIG_BUF_SIZE);
    }

    public ValueFileOutput(Config config, File dir, int bufferCapacity)
                           throws IOException {
        super(bufferCapacity);

        this.maxSegmentSize = config.get(
                              ComputerOptions.VALUE_FILE_MAX_SEGMENT_SIZE);
        E.checkArgument(this.maxSegmentSize <= Integer.MAX_VALUE,
                        "Max size of segment must be smaller than '%s' " +
                        "but get '%s'", Integer.MAX_VALUE, this.maxSegmentSize);
        E.checkArgument(bufferCapacity >= 8 &&
                        bufferCapacity <= this.maxSegmentSize,
                        "The parameter bufferCapacity must be >= 8 " +
                        "and <= %s", this.maxSegmentSize);
        E.checkArgument(dir.isDirectory(),
                        "The parameter dir must be a directory");
        this.dir = dir;
        this.segments = ValueFile.scanSegment(dir);
        this.segmentIndex = -1;
        this.currentSegment = this.nextSegment();
    }

    @Override
    public void write(byte[] b) throws IOException {
        this.write(b, 0, b.length);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (this.bufferAvailable() >= len) {
            super.write(b, off, len);
            return;
        }

        this.flushBuffer();
        if (this.bufferCapacity() >= len) {
            super.write(b, off, len);
            return;
        }

        int remain = this.currentSegmentRemain();
        if (remain >= len) {
            this.currentSegment.write(b, off, len);
        } else {
            int tempLen = len;
            int offset = off;
            this.currentSegment.write(b, offset, remain);

            tempLen -= remain;
            offset += remain;

            /*
             * The read length maybe greater than the size of multiple segments.
             * So need to write multiple segments.
             */
            while (true) {
                this.currentSegment.close();
                this.currentSegment = this.nextSegment();
                if (tempLen > this.maxSegmentSize) {
                    this.currentSegment.write(b, offset,
                                              (int) this.maxSegmentSize);
                    tempLen -= this.maxSegmentSize;
                    offset += this.maxSegmentSize;
                } else {
                    this.currentSegment.write(b, offset, tempLen);
                    break;
                }
            }
        }
        this.fileOffset += len;
    }

    @Override
    public void seek(long position) throws IOException {
        E.checkArgument(position >= 0,
                        "Parameter position must >= 0, but get '%s'",
                        position);
        if (this.fileOffset <= position && position <= this.position()) {
            super.seek(position - this.fileOffset);
            return;
        }

        int segmentIndex = (int) (position / this.maxSegmentSize);
        if (segmentIndex >= this.segments.size()) {
            throw new EOFException(String.format(
                      "Can't seek to %s, reach the end of file",
                      position));
        }

        this.flushBuffer();
        if (segmentIndex != this.segmentIndex) {
            this.currentSegment.close();
            this.currentSegment = new RandomAccessFile(
                                  this.segments.get(segmentIndex),
                                  Constants.FILE_MODE_WRITE);
            this.segmentIndex = segmentIndex;
        }
        long seekPosition = position - segmentIndex * this.maxSegmentSize;
        this.currentSegment.seek(seekPosition);
        this.fileOffset = position;
    }

    @Override
    public void close() throws IOException {
        this.flushBuffer();
        this.currentSegment.close();
    }

    @Override
    public void flushBuffer() throws IOException {
        int segmentRemain = this.currentSegmentRemain();
        int bufferSize = super.bufferSize();

        if (segmentRemain >= bufferSize) {
            this.currentSegment.write(super.buffer(), 0, bufferSize);
        } else {
            this.currentSegment.write(super.buffer(), 0, segmentRemain);
            this.currentSegment.close();
            this.currentSegment = this.nextSegment();
            this.currentSegment.write(super.buffer(), segmentRemain,
                                      bufferSize - segmentRemain);
        }
        this.fileOffset += bufferSize;
        super.seek(0L);
    }

    private RandomAccessFile nextSegment() throws IOException {
        File segment;
        if (++this.segmentIndex < this.segments.size()) {
            segment = this.segments.get(this.segmentIndex);
        } else {
            segment = ValueFile.segmentFromId(this.dir, this.segmentIndex);
            this.segments.add(segment);
        }

        if (!segment.exists()) {
            boolean result = segment.createNewFile();
            E.checkState(result, "Failed to create segment '%s'",
                         segment.getAbsolutePath());
        }
        return new RandomAccessFile(segment, Constants.FILE_MODE_WRITE);
    }

    private int currentSegmentRemain() throws IOException {
        long remain = this.maxSegmentSize -
                      this.currentSegment.getFilePointer();
        return (int) remain;
    }
}
