﻿using System;
using System.Globalization;

namespace Lucene.Net.Codecs.SimpleText
{
    /*
     * 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.
     */

    using CorruptIndexException = Index.CorruptIndexException;
    using ChecksumIndexInput = Store.ChecksumIndexInput;
    using DataInput = Store.DataInput;
    using DataOutput = Store.DataOutput;
    using IndexOutput = Store.IndexOutput;
    using BytesRef = Util.BytesRef;
    using StringHelper = Util.StringHelper;
    using UnicodeUtil = Util.UnicodeUtil;

    internal class SimpleTextUtil
    {
        public static readonly byte NEWLINE = 10;
        public static readonly byte ESCAPE = 92;
        internal static readonly BytesRef CHECKSUM = new BytesRef("checksum ");

        public static void Write(DataOutput output, string s, BytesRef scratch)
        {
            UnicodeUtil.UTF16toUTF8(s.ToCharArray(), 0, s.Length, scratch);
            Write(output, scratch);
        }

        public static void Write(DataOutput output, BytesRef b)
        {
            for (var i = 0; i < b.Length; i++)
            {
                var bx = b.Bytes[b.Offset + i];
                if (bx == NEWLINE || bx == ESCAPE)
                {
                    output.WriteByte(ESCAPE);
                }
                output.WriteByte(bx);
            }
        }

        public static void WriteNewline(DataOutput output)
        {
            output.WriteByte(NEWLINE);
        }

        public static void ReadLine(DataInput input, BytesRef scratch)
        {
            var upto = 0;
            while (true)
            {
                var b = input.ReadByte();
                if (scratch.Bytes.Length == upto)
                {
                    scratch.Grow(1 + upto);
                }
                if (b == ESCAPE)
                {
                    scratch.Bytes[upto++] = input.ReadByte();
                }
                else
                {
                    if (b == NEWLINE)
                    {
                        break;
                    }
                    
                    scratch.Bytes[upto++] = b;
                }
            }
            scratch.Offset = 0;
            scratch.Length = upto;
        }

        public static void WriteChecksum(IndexOutput output, BytesRef scratch)
        {
            // Pad with zeros so different checksum values use the
            // same number of bytes
            // (BaseIndexFileFormatTestCase.testMergeStability cares):
            var checksum = string.Format(CultureInfo.InvariantCulture, "{0:D20}", output.Checksum);
            Write(output, CHECKSUM);
            Write(output, checksum, scratch);
            WriteNewline(output);
        }

        public static void CheckFooter(ChecksumIndexInput input)
        {
            var scratch = new BytesRef();
            var expectedChecksum = string.Format(CultureInfo.InvariantCulture, "{0:D20}", input.Checksum);
            ReadLine(input, scratch);

            if (StringHelper.StartsWith(scratch, CHECKSUM) == false)
            {
                throw new CorruptIndexException("SimpleText failure: expected checksum line but got " +
                                                scratch.Utf8ToString() + " (resource=" + input + ")");
            }
            var actualChecksum =
                (new BytesRef(scratch.Bytes, CHECKSUM.Length, scratch.Length - CHECKSUM.Length)).Utf8ToString();
            if (!expectedChecksum.Equals(actualChecksum, StringComparison.Ordinal))
            {
                throw new CorruptIndexException("SimpleText checksum failure: " + actualChecksum + " != " +
                                                expectedChecksum + " (resource=" + input + ")");
            }
            if (input.Length != input.GetFilePointer())
            {
                throw new CorruptIndexException(
                    "Unexpected stuff at the end of file, please be careful with your text editor! (resource=" + input +
                    ")");
            }
        }
    }
}