/*
 *  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
 *
 *      https://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 org.apache.ivy.core;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.ivy.Ivy;
import org.apache.ivy.core.event.EventManager;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
import org.apache.ivy.util.Message;
import org.apache.ivy.util.MessageLogger;

/**
 * This class represents an execution context of an Ivy action. It contains several getters to
 * retrieve information, like the used Ivy instance, the cache location...
 *
 * @see IvyThread
 */
public class IvyContext {

    private static ThreadLocal<Stack<IvyContext>> current = new ThreadLocal<>();

    private Ivy defaultIvy;

    private WeakReference<Ivy> ivy = new WeakReference<>(null);

    private Map<String, Object> contextMap = new HashMap<>();

    private Thread operatingThread;

    private ResolveData resolveData;

    private DependencyDescriptor dd;

    public IvyContext() {
    }

    public IvyContext(IvyContext ctx) {
        defaultIvy = ctx.defaultIvy;
        ivy = ctx.ivy;
        contextMap = new HashMap<>(ctx.contextMap);
        operatingThread = ctx.operatingThread;
        resolveData = ctx.resolveData;
        dd = ctx.dd;
    }

    public static IvyContext getContext() {
        Stack<IvyContext> cur = getCurrentStack();
        if (cur.isEmpty()) {
            cur.push(new IvyContext());
        }
        return cur.peek();
    }

    private static Stack<IvyContext> getCurrentStack() {
        Stack<IvyContext> cur = current.get();
        if (cur == null) {
            cur = new Stack<>();
            current.set(cur);
        }
        return cur;
    }

    /**
     * Creates a new IvyContext and pushes it as the current context in the current thread.
     * <p>
     * {@link #popContext()} should usually be called when the job for which this context has been
     * pushed is finished.
     * </p>
     *
     * @return the newly pushed context
     */
    public static IvyContext pushNewContext() {
        return pushContext(new IvyContext());
    }

    /**
     * Creates a new IvyContext as a copy of the current one and pushes it as the current context in
     * the current thread.
     * <p>
     * {@link #popContext()} should usually be called when the job for which this context has been
     * pushed is finished.
     * </p>
     *
     * @return the newly pushed context
     */
    public static IvyContext pushNewCopyContext() {
        return pushContext(new IvyContext(getContext()));
    }

    /**
     * Changes the context associated with this thread. This is especially useful when launching a
     * new thread, to associate it with the same context as the initial one. Do not forget to call
     * {@link #popContext()} when done.
     *
     * @param context
     *            the new context to use in this thread.
     * @return the pushed context
     */
    public static IvyContext pushContext(IvyContext context) {
        getCurrentStack().push(context);
        return context;
    }

    /**
     * Pops one context used with this thread. This is usually called after having finished a task
     * for which a call to {@link #pushNewContext()} or {@link #pushContext(IvyContext)} was done
     * prior to beginning the task.
     *
     * @return the popped context
     */
    public static IvyContext popContext() {
        return getCurrentStack().pop();
    }

    /**
     * Reads the first object from the list saved under given key in the first context from the
     * context stack in which this key is defined. If value under key in any of the contexts form
     * the stack represents non List object then a RuntimeException is thrown.
     * <p>
     * This methods does a similar job to {@link #peek(String)}, except that it considers the whole
     * context stack and not only one instance.
     * </p>
     *
     * @param key
     *            context key for the string
     * @return top object from the list (index 0) of the first context in the stack containing this
     *         key or null if no key or list empty in all contexts from the context stack
     * @see #peek(String)
     */
    public static Object peekInContextStack(String key) {
        Object value = null;
        Stack<IvyContext> contextStack = getCurrentStack();
        for (int i = contextStack.size() - 1; i >= 0 && value == null; i--) {
            IvyContext ctx = contextStack.get(i);
            value = ctx.peek(key);
        }
        return value;
    }

    /**
     * Returns the current ivy instance.
     * <p>
     * When calling any public ivy method on an ivy instance, a reference to this instance is put in
     * this context, and thus accessible using this method, until no code reference this instance
     * and the garbage collector collects it.
     * </p>
     * <p>
     * Then, or if no ivy method has been called, a default ivy instance is returned by this method,
     * so that it never returns <code>null</code>.
     * </p>
     *
     * @return the current ivy instance
     */
    public Ivy getIvy() {
        Ivy ivy = peekIvy();
        return ivy == null ? getDefaultIvy() : ivy;
    }

    /**
     * Returns the Ivy instance associated with this context, or <code>null</code> if no such
     * instance is currently associated with this context.
     * <p>
     * If you want get a default Ivy instance in case no instance if currently associated, use
     * {@link #getIvy()}.
     * </p>
     *
     * @return the current ivy instance, or <code>null</code> if there is no current ivy instance.
     */
    public Ivy peekIvy() {
        return this.ivy.get();
    }

    private Ivy getDefaultIvy() {
        if (defaultIvy == null) {
            defaultIvy = Ivy.newInstance();
            try {
                defaultIvy.configureDefault();
            } catch (Exception e) {
                Message.debug(e);
                // ???
            }
        }
        return defaultIvy;
    }

    public void setIvy(Ivy ivy) {
        this.ivy = new WeakReference<>(ivy);
        operatingThread = Thread.currentThread();
    }

    public IvySettings getSettings() {
        return getIvy().getSettings();
    }

    public CircularDependencyStrategy getCircularDependencyStrategy() {
        return getSettings().getCircularDependencyStrategy();
    }

    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        WeakReference<T> ref = (WeakReference<T>) contextMap.get(key);
        return (ref == null) ? null : ref.get();
    }

    public <T> void set(String key, T value) {
        contextMap.put(key, new WeakReference<>(value));
    }

    /**
     * Reads the first object from the list saved under given key in the context. If value under key
     * represents non List object then a RuntimeException is thrown.
     *
     * @param key
     *            context key for the string
     * @return top object from the list (index 0) or null if no key or list empty
     */
    @SuppressWarnings("unchecked")
    public Object peek(String key) {
        synchronized (contextMap) {
            Object o = contextMap.get(key);
            if (o == null) {
                return null;
            }
            if (o instanceof List) {
                if (((List<Object>) o).size() == 0) {
                    return null;
                }
                return ((List<Object>) o).get(0);
            } else {
                throw new RuntimeException("Cannot top from non List object " + o);
            }
        }
    }

    /**
     * Removes and returns first object from the list saved under given key in the context. If value
     * under key represents non List object then a RuntimeException is thrown.
     *
     * @param key
     *            context key for the string
     * @return top object from the list (index 0) or null if no key or list empty
     */
    @SuppressWarnings("unchecked")
    public Object pop(String key) {
        synchronized (contextMap) {
            Object o = contextMap.get(key);
            if (o == null) {
                return null;
            }
            if (o instanceof List) {
                if (((List<Object>) o).size() == 0) {
                    return null;
                }
                return ((List<Object>) o).remove(0);
            } else {
                throw new RuntimeException("Cannot pop from non List object " + o);
            }
        }
    }

    /**
     * Removes and returns first object from the list saved under given key in the context but only
     * if it equals the given expectedValue - if not a false value is returned. If value under key
     * represents non List object then a RuntimeException is thrown.
     *
     * @param key
     *            context key for the string
     * @param expectedValue
     *            expected value of the key
     * @return true if the r
     */
    @SuppressWarnings("unchecked")
    public boolean pop(String key, Object expectedValue) {
        synchronized (contextMap) {
            Object o = contextMap.get(key);
            if (o == null) {
                return false;
            }
            if (o instanceof List) {
                if (((List<Object>) o).size() == 0) {
                    return false;
                }
                Object top = ((List<Object>) o).get(0);
                if (!top.equals(expectedValue)) {
                    return false;
                }
                ((List<Object>) o).remove(0);
                return true;
            } else {
                throw new RuntimeException("Cannot pop from non List object " + o);
            }
        }
    }

    /**
     * Puts a new object at the start of the list saved under given key in the context. If value
     * under key represents non List object then a RuntimeException is thrown. If no list exists
     * under given key a new LinkedList is created. This is kept without WeakReference in opposite
     * to the put() results.
     *
     * @param key
     *            key context key for the string
     * @param value
     *            value to be saved under the key
     */
    @SuppressWarnings("unchecked")
    public void push(String key, Object value) {
        synchronized (contextMap) {
            if (!contextMap.containsKey(key)) {
                contextMap.put(key, new LinkedList<>());
            }
            Object o = contextMap.get(key);
            if (o instanceof List) {
                ((List<Object>) o).add(0, value);
            } else {
                throw new RuntimeException("Cannot push to non List object " + o);
            }
        }
    }

    public Thread getOperatingThread() {
        return operatingThread;
    }

    public MessageLogger getMessageLogger() {
        // calling getIvy() instead of peekIvy() is not possible here: it will initialize a default
        // Ivy instance, with default settings, but settings themselves may log messages and lead to
        // a call to this method. So we use the current Ivy instance if any, or the default Ivy
        // instance, or the default MessageLogger.
        Ivy ivy = peekIvy();
        if (ivy == null) {
            if (defaultIvy == null) {
                return Message.getDefaultLogger();
            } else {
                return defaultIvy.getLoggerEngine();
            }
        } else {
            return ivy.getLoggerEngine();
        }
    }

    public EventManager getEventManager() {
        return getIvy().getEventManager();
    }

    public void checkInterrupted() {
        getIvy().checkInterrupted();
    }

    public void setResolveData(ResolveData data) {
        this.resolveData = data;
    }

    public ResolveData getResolveData() {
        return resolveData;
    }

    public void setDependencyDescriptor(DependencyDescriptor dd) {
        this.dd = dd;
    }

    public DependencyDescriptor getDependencyDescriptor() {
        return dd;
    }

}
