/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * Licensed 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 io.aeron.archiver;

import io.aeron.archiver.codecs.RecordingDescriptorDecoder;
import org.agrona.IoUtil;
import org.agrona.concurrent.UnsafeBuffer;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Date;

import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;

public class ArchiveUtil
{
    static String recordingMetaFileName(final long recordingId)
    {
        return recordingId + ".inf";
    }

    static String recordingDataFileName(
        final long recordingId,
        final int segmentIndex)
    {
        return recordingId + "." + segmentIndex + ".rec";
    }

    static String recordingDataFileName(
        final long recordingId,
        final int initialTermId,
        final int termBufferLength,
        final int termId,
        final int segmentFileLength)
    {
        final int segmentIndex = segmentFileIndex(initialTermId, termId, termBufferLength, segmentFileLength);

        return recordingDataFileName(recordingId, segmentIndex);
    }

    private static int segmentFileIndex(
        final int initialTermId,
        final int termId,
        final int termBufferLength,
        final int segmentFileLength)
    {
        return (int) (((termId - initialTermId) * (long)termBufferLength) / segmentFileLength);
    }

    static int segmentFileIndex(
        final long joiningPosition,
        final long position,
        final int segmentFileLength)
    {
        return (int)((position - joiningPosition) / segmentFileLength);
    }

    static void printMetaFile(final File metaFile) throws IOException
    {
        final RecordingDescriptorDecoder formatDecoder = recordingMetaFileFormatDecoder(metaFile);
        System.out.println("recordingId: " + formatDecoder.recordingId());
        System.out.println("termBufferLength: " + formatDecoder.termBufferLength());
        System.out.println("start time: " + new Date(formatDecoder.startTime()));
        System.out.println("joining position: " + formatDecoder.joiningPosition());
        System.out.println("last position: " + formatDecoder.lastPosition());
        System.out.println("end time: " + new Date(formatDecoder.endTime()));
        System.out.println("source: " + formatDecoder.source());
        System.out.println("sessionId: " + formatDecoder.sessionId());
        System.out.println("channel: " + formatDecoder.channel());
        System.out.println("streamId: " + formatDecoder.streamId());
        IoUtil.unmap(formatDecoder.buffer().byteBuffer());
    }

    static RecordingDescriptorDecoder recordingMetaFileFormatDecoder(final File metaFile)
        throws IOException
    {
        try (FileChannel metadataFileChannel = FileChannel.open(metaFile.toPath(), READ, WRITE))
        {
            final ByteBuffer metaDataBuffer = ByteBuffer.allocate(Catalog.RECORD_LENGTH);
            metadataFileChannel.read(metaDataBuffer);
            final RecordingDescriptorDecoder decoder = new RecordingDescriptorDecoder();
            return decoder.wrap(
                new UnsafeBuffer(metaDataBuffer),
                Catalog.CATALOG_FRAME_LENGTH,
                RecordingDescriptorDecoder.BLOCK_LENGTH,
                RecordingDescriptorDecoder.SCHEMA_VERSION);
        }
    }

    static int recordingOffset(
        final int termOffset,
        final int termId,
        final int initialTermId,
        final int termsMask,
        final int termBufferLength)
    {
        return ((termId - initialTermId) & termsMask) * termBufferLength + termOffset;
    }

    static long recordingFileFullLength(final RecordingDescriptorDecoder metaDecoder)
    {
        return metaDecoder.lastPosition() - metaDecoder.joiningPosition();
    }

    public static long recordingLength(
        final int termBufferLength,
        final int initialTermId,
        final int initialTermOffset,
        final int lastTermId, final int lastTermOffset)
    {
        return ((long)(lastTermId - initialTermId)) * termBufferLength +
            (lastTermOffset - initialTermOffset);
    }
}

@@ -1288,685 +1288,8 @@
  %7D%0A%0A
-    static String recordingDataFileName(%0A        final long recordingId,%0A        final int initialTermId,%0A        final int termBufferLength,%0A        final int termId,%0A        final int segmentFileLength)%0A    %7B%0A        final int segmentIndex = segmentFileIndex(initialTermId, termId, termBufferLength, segmentFileLength);%0A%0A        return recordingDataFileName(recordingId, segmentIndex);%0A    %7D%0A%0A    private static int segmentFileIndex(%0A        final int initialTermId,%0A        final int termId,%0A        final int termBufferLength,%0A        final int segmentFileLength)%0A    %7B%0A        return (int) (((termId - initialTermId) * (long)termBufferLength) / segmentFileLength);%0A    %7D%0A%0A
     
@@ -1317,16 +1317,16 @@
 eIndex(%0A
+
         
@@ -1572,32 +1572,117 @@
 Exception%0A    %7B%0A
+        // TODO: Take a different approach to mapping and unmapping for such a case.%0A
         final Re
@@ -2958,16 +2958,17 @@
 uffer);%0A
+%0A
         
@@ -2975,50 +2975,14 @@
     
-final RecordingDescriptorDecoder decoder =
+return
  new
@@ -3014,36 +3014,8 @@
 er()
-;%0A            return decoder
 .wra
@@ -3617,32 +3617,32 @@
 aDecoder)%0A    %7B%0A
+
         return m
@@ -3709,345 +3709,7 @@
    %7D
-%0A%0A    public static long recordingLength(%0A        final int termBufferLength,%0A        final int initialTermId,%0A        final int initialTermOffset,%0A        final int lastTermId, final int lastTermOffset)%0A    %7B%0A        return ((long)(lastTermId - initialTermId)) * termBufferLength +%0A            (lastTermOffset - initialTermOffset);%0A    %7D
 %0A%7D%0A

Remove unused methods and add a TODO.