#region License

/*
 * 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.
 */

#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Gremlin.Net.Process.Traversal
{
    /// <summary>
    ///     A language agnostic representation of <see cref="ITraversal" /> mutations.
    /// </summary>
    /// <remarks>
    ///     Bytecode is simply a list of ordered instructions.
    ///     Bytecode can be serialized between environments and machines by way of a GraphSON representation.
    ///     Thus, Gremlin.Net can create bytecode in C# and ship it to Gremlin-Java for evaluation in Java.
    /// </remarks>
    public class Bytecode
    {
        private static readonly object[] EmptyArray = Array.Empty<object>();

        /// <summary>
        ///     Initializes a new instance of the <see cref="Bytecode" /> class.
        /// </summary>
        public Bytecode()
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Bytecode" /> class.
        /// </summary>
        /// <param name="byteCode">Already existing <see cref="Bytecode" /> that should be cloned.</param>
        public Bytecode(Bytecode byteCode)
        {
            SourceInstructions = new List<Instruction>(byteCode.SourceInstructions);
            StepInstructions = new List<Instruction>(byteCode.StepInstructions);
        }

        /// <summary>
        ///     Gets the traversal source instructions.
        /// </summary>
        public List<Instruction> SourceInstructions { get; } = new List<Instruction>();

        /// <summary>
        ///     Gets the <see cref="ITraversal" /> instructions.
        /// </summary>
        public List<Instruction> StepInstructions { get; } = new List<Instruction>();

        /// <summary>
        ///     Add a traversal source instruction to the bytecode.
        /// </summary>
        /// <param name="sourceName">The traversal source method name (e.g. withSack()).</param>
        /// <param name="args">The traversal source method arguments.</param>
        public void AddSource(string sourceName, params object[] args)
        {
            SourceInstructions.Add(new Instruction(sourceName, FlattenArguments(args)));
            Bindings.Clear();
        }

        /// <summary>
        ///     Adds a <see cref="ITraversal" /> instruction to the bytecode.
        /// </summary>
        /// <param name="stepName">The traversal method name (e.g. out()).</param>
        /// <param name="args">The traversal method arguments.</param>
        public void AddStep(string stepName, params object[] args)
        {
            StepInstructions.Add(new Instruction(stepName, FlattenArguments(args)));
            Bindings.Clear();
        }

        private object[] FlattenArguments(object[] arguments)
        {
            if (arguments.Length == 0)
                return EmptyArray;
            var flatArguments = new List<object>();
            foreach (var arg in arguments)
            {
                if (arg is object[] objects)
                {
                    flatArguments.AddRange(objects.Select(nestObject => ConvertArgument(nestObject, true)));
                }
                else
                {
                    flatArguments.Add(ConvertArgument(arg, true));
                }
            }
            return flatArguments.ToArray();
        }

        private object ConvertArgument(object argument, bool searchBindings)
        {
            if (null == argument)
            {
                return null;
            }

            if (searchBindings)
            {
                var variable = Bindings.GetBoundVariable(argument);
                if (variable != null)
                    return new Binding(variable, ConvertArgument(argument, false));
            }

            if (argument is ITraversal traversal && !traversal.IsAnonymous)
                throw new ArgumentException(
                    $"The child traversal of {traversal.Bytecode} was not spawned anonymously - use the __ class rather than a TraversalSource to construct the child traversal");

            
            if (IsDictionaryType(argument.GetType()))
            {
                var dict = new Dictionary<object, object>();
                foreach (DictionaryEntry item in (IDictionary)argument)
                {
                    dict[ConvertArgument(item.Key, true)] = ConvertArgument(item.Value, true);
                }
                return dict;
            }
            if (IsListType(argument.GetType()))
            {
                var list = new List<object>(((IList) argument).Count);
                list.AddRange(from object item in (IList) argument select ConvertArgument(item, true));
                return list;
            }
            if (IsHashSetType(argument.GetType()))
            {
                var set = new HashSet<object>();
                foreach (var item in (IEnumerable)argument)
                {
                    set.Add(ConvertArgument(item, true));
                }
                return set;
            }
            return argument;
        }

        private bool IsDictionaryType(Type type)
        {
            return type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
        }

        private bool IsListType(Type type)
        {
            return type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(List<>);
        }

        private bool IsHashSetType(Type type)
        {
            return type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>);
        }

        /// <inheritdoc />
        public override string ToString()
        {
            return $"[[{string.Join(", ", SourceInstructions)}], [{string.Join(", ", StepInstructions)}]]";
        }
    }
}
