using Lucene.Net.Benchmarks.ByTask;
using Lucene.Net.Util;
using System;
using System.IO;
using System.Text;
using Console = Lucene.Net.Support.SystemConsole;

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

    /// <summary>
    /// Base class for all Benchmark unit tests.
    /// </summary>
    public abstract class BenchmarkTestCase : LuceneTestCase
    {
        private static DirectoryInfo WORKDIR;

        public override void BeforeClass()
        {
            base.BeforeClass();
            WORKDIR = CreateTempDir("benchmark");
            // LUCENENET: Our directory numbers are sequential. Doing a delete
            // here will make threads collide.
            //WORKDIR.Delete();
            //WORKDIR.Create();

            propLines = new string[] {
                "work.dir=" + getWorkDirPath(),
                "directory=RAMDirectory",
                "print.props=false",
            };
        }

        public override void AfterClass()
        {
            WORKDIR = null;
            base.AfterClass();
        }


        public DirectoryInfo getWorkDir()
        {
            return WORKDIR;
        }

        /** Copy a resource into the workdir */
        public void copyToWorkDir(string resourceName)
        {
            Stream resource = GetType().getResourceAsStream(resourceName);
            Stream dest = new FileStream(System.IO.Path.Combine(getWorkDir().FullName, resourceName), FileMode.Create, FileAccess.Write);
            byte[] buffer = new byte[8192];
            int len;

            while ((len = resource.Read(buffer, 0, buffer.Length)) > 0)
            {
                dest.Write(buffer, 0, len);
            }

            resource.Dispose();
            dest.Dispose();
        }

        /** Return a path, suitable for a .alg config file, for a resource in the workdir */
        public String getWorkDirResourcePath(String resourceName)
        {
            return System.IO.Path.Combine(getWorkDir().FullName, resourceName).Replace("\\", "/");
        }

        /** Return a path, suitable for a .alg config file, for the workdir */
        public String getWorkDirPath()
        {
            return getWorkDir().FullName.Replace("\\", "/");
        }

        // create the benchmark and execute it. 
        public Benchmark execBenchmark(String[] algLines)
        {
            String algText = algLinesToText(algLines);
            logTstLogic(algText);
            Benchmark benchmark = new Benchmark(new StringReader(algText));
            benchmark.Execute();
            return benchmark;
        }

        // properties in effect in all tests here
        String[] propLines;

        static readonly String NEW_LINE = Environment.NewLine;

        // catenate alg lines to make the alg text
        private String algLinesToText(String[] algLines)
        {
            String indent = "  ";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < propLines.Length; i++)
            {
                sb.append(indent).append(propLines[i]).append(NEW_LINE);
            }
            for (int i = 0; i < algLines.Length; i++)
            {
                sb.append(indent).append(algLines[i]).append(NEW_LINE);
            }
            return sb.toString();
        }

        private static void logTstLogic(String txt)
        {
            if (!VERBOSE)
                return;
            Console.WriteLine("Test logic of:");
            Console.WriteLine(txt);
        }
    }
}
