/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * 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 com.jetbrains.python.psi.impl;

import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
* @author yole
*/
public class CallArgumentsMappingImpl implements CallArgumentsMapping {

  private final Map<PyExpression, PyNamedParameter> myPlainMappedParams; // one param per arg
  private final Map<PyExpression, List<PyNamedParameter>> myNestedMappedParams; // one arg sweeps a nested tuple of params
  private PyStarArgument myTupleArg; // the *arg
  private PyStarArgument myKwdArg;   // the **arg
  private final List<PyNamedParameter> myTupleMappedParams; // params mapped to *arg
  private final List<PyNamedParameter> myKwdMappedParams;   // params mapped to **arg
  private final List<PyNamedParameter> myUnmappedParams;
  private final Map<PyExpression, EnumSet<ArgFlag>> myArgFlags; // flags of every arg
  private PyCallExpression.PyMarkedCallee myMarkedCallee;
  private PyArgumentList myArgumentList;

  public CallArgumentsMappingImpl(PyArgumentList arglist) {
    // full of empty containers
    myPlainMappedParams = new LinkedHashMap<PyExpression, PyNamedParameter>();
    myNestedMappedParams = new LinkedHashMap<PyExpression, List<PyNamedParameter>>();
    myTupleMappedParams = new ArrayList<PyNamedParameter>();
    myKwdMappedParams = new ArrayList<PyNamedParameter>();
    myUnmappedParams = new ArrayList<PyNamedParameter>();
    myArgFlags = new HashMap<PyExpression, EnumSet<ArgFlag>>();
    myMarkedCallee = null;
    myArgumentList = arglist;
  }

  /**
   * Maps arguments of a call to parameters of a callee.
   * must contain already resolved callee with flags set appropriately.
   * <br/>
   * <i>NOTE:</i> <tt>*arg</tt> of unknown length is considered to be long just enough to fill appropriate
   * positional paramaters, but at least one item long.
   * @param arguments what to map, get if from call site
   * @param resolved_callee what to map parameters of
   * @param context optional shared type evaluator / cache.
   */
  public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @NotNull TypeEvalContext context) {
    PyExpression[] arguments = myArgumentList.getArguments();
    myMarkedCallee = resolved_callee;
    final List<PyExpression> unmatched_subargs = new LinkedList<PyExpression>(); // unmatched nested arguments will go here
    List<PyExpression> unmatched_args = verifyArguments();

    final List<PyParameter> parameters = PyUtil.getParameters(myMarkedCallee.getCallable(), context);
    // prepare parameter slots
    Map<PyNamedParameter, PyExpression> slots = new LinkedHashMap<PyNamedParameter, PyExpression>();
    PyNamedParameter kwd_par = null;   // **param
    PyNamedParameter tuple_par = null; // *param
    Set<PyExpression> mapped_args = new HashSet<PyExpression>();
    final int implicitOffset = resolved_callee.getImplicitOffset();
    int positional_index = 0; // up to this index parameters are positional
    // check positional arguments, fill slots
    int i = 0;
    for (PyParameter par : parameters) {
      if (tuple_par == null && kwd_par == null && positional_index < implicitOffset) {
        positional_index += 1;
        continue;
      }
      PyNamedParameter n_par = par.getAsNamed();
      if (n_par != null) {
        if (n_par.isPositionalContainer()) tuple_par = n_par;
        else if (n_par.isKeywordContainer()) kwd_par = n_par;
        else {
          slots.put(n_par, null); // regular parameter that may serve as positional/named
          if (tuple_par == null && kwd_par == null) {
            positional_index += 1; // only if we're not past *param / **param
          }
        }
      }
      else {
        PyTupleParameter t_par = par.getAsTuple();
        if (t_par != null) positional_index += 1; // tuple can only be positional
        // else lone star, skip
      }
      i += 1;
    }
    // rule out 'self' or other implicit params
    for (i=0; i < implicitOffset && i < parameters.size(); i+=1) {
      slots.remove(parameters.get(i).getAsNamed());
      positional_index += 1;
    }
    // now params to the left of positional_index are positional.
    // map positional args to positional params.
    // we assume that implicitly skipped parameters are never nested tuples. no idea when they could ever be.
    int cnt = implicitOffset;
    int positional_bound = arguments.length; // to the right of this pos args are verboten
    ListIterator<PyExpression> unmatched_arg_iter = unmatched_args.listIterator();
    while (unmatched_arg_iter.hasNext()) {
      PyExpression arg = unmatched_arg_iter.next();
      if (arg instanceof PyStarArgument || arg instanceof PyKeywordArgument) {
        positional_bound = cnt;
        break;
      }
      if (cnt < parameters.size() && cnt < positional_index) {
        final PyParameter par = parameters.get(cnt);
        PyNamedParameter n_par = par.getAsNamed();
        if (n_par != null) {
          cnt += 1;
          slots.put(n_par, PyUtil.peelArgument(arg));
          mapped_args.add(arg);
        }
        else {
          PyTupleParameter t_par = par.getAsTuple();
          if (t_par != null) {
            if (arg instanceof PyParenthesizedExpression) {
              mapped_args.add(arg); // tuple itself is always mapped; its insides can fail
            }
            else {
              PyType arg_type = context.getType(arg);
              if (arg_type != null && arg_type.isBuiltin() && "list".equals(arg_type.getName())) {
                mapped_args.add(arg); // we can't really analyze arbitrary lists statically yet
                // but ListLiteralExpressions are handled by visitor
              }
            }
            unmatched_arg_iter.previous();
            MyParamVisitor visitor = new MyParamVisitor(unmatched_arg_iter, this);
            visitor.enterTuple(t_par.getAsTuple()); // will recur as needed
            unmatched_subargs.addAll(visitor.getUnmatchedSubargs()); // what didn't match inside
            cnt += 1;
          }
          // else: goes to *param
        }
      }
      else break;
    }
    // anything left after mapping of nested-tuple params?
    for (Map.Entry<PyExpression, List<PyNamedParameter>> pair : myNestedMappedParams.entrySet()) {
      PyExpression arg = pair.getKey();
      List<PyNamedParameter> params = pair.getValue();
      mapped_args.add(arg);
      for (PyNamedParameter n_par : params) slots.remove(n_par);
    }
    for (PyExpression arg : unmatched_subargs) {
      markArgument(arg, ArgFlag.IS_UNMAPPED);
    }


    boolean seen_named_args = false;
    // map named args to named params if possible
    Map<String, PyNamedParameter> parameter_by_name = new LinkedHashMap<String, PyNamedParameter>();
    for (PyParameter par : parameters) {
      PyNamedParameter n_par = par.getAsNamed();
      if (n_par != null) parameter_by_name.put(n_par.getName(), n_par);
    }
    for (PyExpression arg : arguments) {
      if (arg instanceof PyKeywordArgument) { // to explicitly named param?
        String arg_name = ((PyKeywordArgument)arg).getKeyword();
        PyNamedParameter respective_par = parameter_by_name.get(arg_name);
        if (respective_par != null && !respective_par.isKeywordContainer() && !respective_par.isPositionalContainer()) {
          if (slots.get(respective_par) != null) markArgument(arg, ArgFlag.IS_DUP);
          else slots.put(respective_par, arg);
        }
        else { // to **param?
          if (kwd_par != null) {
            myPlainMappedParams.put(arg, kwd_par);
            mapped_args.add(arg);
          }
        }
        seen_named_args = true;
      }
    }
    // map *arg to positional params if possible
    boolean tuple_arg_not_exhausted = false;
    boolean tuple_dup_found = false;
    if (cnt < parameters.size() && cnt < positional_index && myTupleArg != null) {
      // check length of myTupleArg
      PyType tuple_arg_type = null;
      final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
      if (expression != null) {
        tuple_arg_type = context.getType(expression);
      }
      int tuple_length;
      boolean tuple_length_known;
      if (tuple_arg_type instanceof PyTupleType) {
        tuple_length = ((PyTupleType)tuple_arg_type).getElementCount();
        tuple_length_known = true;
      }
      else {
        tuple_length = 2000000; // no practical function will have so many positional params
        tuple_length_known = false;
      }
      int mapped_params_count = 0;
      while (cnt < parameters.size() && cnt < positional_index && mapped_params_count < tuple_length) {
        PyParameter par = parameters.get(cnt);
        if (par instanceof PySingleStarParameter) break;
        PyNamedParameter n_par = par.getAsNamed();
        if (slots.containsKey(n_par)) {
          final PyExpression arg_here = slots.get(n_par);
          if (arg_here != null) {
            if (tuple_length_known) {
              final EnumSet<ArgFlag> flags = myArgFlags.get(arg_here);
              if (flags == null || flags.isEmpty()) {
                markArgument(arg_here, ArgFlag.IS_DUP);
                tuple_dup_found = true;
              }
            }
            // else: unknown tuple length is just enough
            // the spree is over
            break;
          }
          else if (n_par != null) { // normally always true
            myTupleMappedParams.add(n_par);
            mapped_args.add(myTupleArg);
            slots.remove(n_par);
          }
        }
        else if (n_par == tuple_par) {
          mapped_params_count = tuple_length; // we found *param for our *arg, consider it fully mapped
          break;
        }
        cnt += 1;
        mapped_params_count += 1;
      }
      if (
        tuple_length_known && (mapped_params_count < tuple_length) || // not exhausted
        mapped_params_count == 0 // unknown length must consume at least first param
        ) {
        tuple_arg_not_exhausted = true;
      }
    }
    // map *param to the leftmost chunk of unmapped positional args
    // NOTE: ignores the structure of nested-tuple params!
    if (tuple_par != null) {
      i = 0;
      while (i < arguments.length && mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
        i += 1; // skip first mapped args
      }
      if (i < arguments.length && isPositionalArg(arguments[i])) {
        while (i < arguments.length && !mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
          myPlainMappedParams.put(arguments[i], tuple_par);
          mapped_args.add(arguments[i]);
          i += 1;
        }
      }
    }
    // map unmapped *arg to *param
    if (myTupleArg != null && tuple_par != null) {
      if (!mapped_args.contains(myTupleArg)) {
        myTupleMappedParams.add(tuple_par);
        mapped_args.add(myTupleArg);
      }
      else if (! seen_named_args && tuple_arg_not_exhausted) {
        // case of (*(1, 2, 3)) -> (a, *b); map the rest of *arg to *param
        myTupleMappedParams.add(tuple_par);
        mapped_args.add(myTupleArg);
        tuple_arg_not_exhausted = false;
      }
    }
    if (tuple_arg_not_exhausted && ! tuple_dup_found) {
      markArgument(myTupleArg, ArgFlag.IS_TOO_LONG);
    }
    // map unmapped named params to **kwarg
    if (myKwdArg != null) {
      for (int j = implicitOffset; j != parameters.size(); ++j) {
        final PyParameter par = parameters.get(j);
        final PyNamedParameter namedParameter = par.getAsNamed();
        if (namedParameter != null && !namedParameter.isKeywordContainer()
            && !namedParameter.isPositionalContainer() && slots.get(namedParameter) == null) {
          slots.put(namedParameter, myKwdArg);
        }
      }
    }
    // map unmapped **kwarg to **param
    if (myKwdArg != null && kwd_par != null && !mapped_args.contains(myKwdArg)) {
      myKwdMappedParams.add(kwd_par);
      mapped_args.add(myKwdArg);
    }
    // fill in ret, mark unmapped named params
    for (Map.Entry<PyNamedParameter, PyExpression> pair : slots.entrySet()) {
      PyNamedParameter n_par = pair.getKey();
      PyExpression arg = pair.getValue();
      if (arg == null) {
        if (!n_par.hasDefaultValue()) myUnmappedParams.add(n_par);
      }
      else {
        if (arg == myTupleArg) {
          myTupleMappedParams.add(n_par);
        }
        else if (arg == myKwdArg) {
          myKwdMappedParams.add(n_par);
        }
        else {
          myPlainMappedParams.put(arg, n_par);
        }
      }
    }
    // mark unmapped args
    for (PyExpression arg : slots.values()) {
      if (arg != null) mapped_args.add(arg);
    }
    for (PyExpression arg : arguments) {
      if (!mapped_args.contains(arg)) {
        final EnumSet<ArgFlag> flags = myArgFlags.get(arg);
        if (flags == null || flags.isEmpty()) {
          markArgument(arg, ArgFlag.IS_UNMAPPED);
        }
      }
    }
  }

  public List<PyExpression> verifyArguments() {
    List<PyExpression> unmatched_args = new LinkedList<PyExpression>();
    Collections.addAll(unmatched_args, myArgumentList.getArguments());
    // detect starred args
    for (PyExpression arg : myArgumentList.getArguments()) {
      if (arg instanceof PyStarArgument) {
        PyStarArgument star_arg = (PyStarArgument)arg;
        if (star_arg.isKeyword()) {
          if (myKwdArg == null) myKwdArg = star_arg;
          else {
            markArgument(arg, ArgFlag.IS_DUP_KWD);
            unmatched_args.remove(arg);
          }
        }
        else {
          if (myTupleArg == null) myTupleArg = star_arg;
          else {
            markArgument(arg, ArgFlag.IS_DUP_TUPLE);
            unmatched_args.remove(arg);
          }
        }
      }
    }

    markPastBoundPositionalArguments(myArgumentList.getArguments());
    return unmatched_args;
  }

  private void markPastBoundPositionalArguments(PyExpression[] arguments) {
    boolean seenKwArg = false;
    boolean seenKeyword = false;
    boolean seenStar = false;
    for (PyExpression arg : arguments) {
      if (arg == myKwdArg) {
        seenKwArg = true;
      }
      else if (arg instanceof PyKeywordArgument) {
        seenKeyword = true;
      }
      else if (arg instanceof PyStarArgument) {
        seenStar = true;
      }

      if (seenKeyword || seenKwArg || seenStar) {
        if (!(arg instanceof PyStarArgument) && (seenKwArg || !(arg instanceof PyKeywordArgument))) {
          markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
        }
      }
    }
  }

  private static boolean isPositionalArg(PyExpression arg) {
    return !(arg instanceof PyKeywordArgument) && !(arg instanceof PyStarArgument);
  }

  /**
   * @return A mapping argument->parameter for non-starred arguments (but includes starred parameters).
   */
  public @NotNull
  Map<PyExpression, PyNamedParameter> getPlainMappedParams() {
    return myPlainMappedParams;
  }

  @NotNull
  public Map<PyExpression, List<PyNamedParameter>> getNestedMappedParams() {
    return myNestedMappedParams;
  }

  /**
   * @return First *arg, or null.
   */
  public PyStarArgument getTupleArg(){
    return myTupleArg;
  }

  /**
   * @return A list of parameters mapped to an *arg.
   */
  public @NotNull List<PyNamedParameter> getTupleMappedParams(){
    return myTupleMappedParams;
  }

  /**
   * @return First **arg, or null.
   */
  public PyStarArgument getKwdArg(){
    return myKwdArg;
  }

  /**
   * @return A list of parameters mapped to an **arg.
   */
  public @NotNull List<PyNamedParameter> getKwdMappedParams(){
    return myKwdMappedParams;
  }

  /**
   * @return A list of parameters for which no arguments were found ('missing').
   */
  public @NotNull
  List<PyNamedParameter> getUnmappedParams(){
    return myUnmappedParams;
  }

  /**
   * @return result of a resolveCallee() against the function call to which the paramater list belongs.
   */
  @Nullable
  public PyCallExpression.PyMarkedCallee getMarkedCallee() {
    return myMarkedCallee;
  }

  /**
   * @return Lists all args with their flags.
   */
  public Map<PyExpression, EnumSet<ArgFlag>> getArgumentFlags(){
    return myArgFlags;
  }

  @Override
  public boolean hasProblems() {
    for (Map.Entry<PyExpression, EnumSet<CallArgumentsMapping.ArgFlag>> arg_entry : myArgFlags.entrySet()) {
      EnumSet<CallArgumentsMapping.ArgFlag> flags = arg_entry.getValue();
      if (!flags.isEmpty()) return true;
    }
    return myUnmappedParams.size() > 0;
  }

  public PyArgumentList getArgumentList() {
    return myArgumentList; // that is, 'outer'
  }

  protected PyExpression markArgument(PyExpression arg, ArgFlag... flags) {
    EnumSet<ArgFlag> argflags = myArgFlags.get(arg);
    if (argflags == null) {
      argflags = EnumSet.noneOf(ArgFlag.class);
    }
    ContainerUtil.addAll(argflags, flags);
    myArgFlags.put(arg, argflags);
    return arg;
  }

  static class MyParamVisitor extends PyElementVisitor {
    private final Iterator<PyExpression> myArgIterator;
    private final CallArgumentsMappingImpl myResult;
    private final List<PyExpression> myUnmatchedSubargs;

    private MyParamVisitor(Iterator<PyExpression> arg_iterator, CallArgumentsMappingImpl ret) {
      myArgIterator = arg_iterator;
      myResult = ret;
      myUnmatchedSubargs = new ArrayList<PyExpression>(5); // arbitrary 'enough'
    }

    private Collection<PyExpression> getUnmatchedSubargs() {
      return myUnmatchedSubargs;
    }

    @Override
    public void visitPyParameter(PyParameter node) {
      PyNamedParameter named = node.getAsNamed();
      if (named != null) enterNamed(named);
      else enterTuple(node.getAsTuple());
    }

    public void enterTuple(PyTupleParameter param) {
      PyExpression arg = null;
      if (myArgIterator.hasNext()) arg = myArgIterator.next();
      // try to unpack a tuple expr in argument, if there's any
      PyExpression[] elements = null;
      if (arg instanceof PyParenthesizedExpression) {
        PyExpression inner_expr = ((PyParenthesizedExpression)arg).getContainedExpression();
        if (inner_expr instanceof PyTupleExpression) elements = ((PyTupleExpression)inner_expr).getElements();
      }
      else if (arg instanceof PyListLiteralExpression) {
        elements = ((PyListLiteralExpression)arg).getElements();
      }
      final PyParameter[] nested_params = param.getContents();
      if (elements != null) { // recursively map expression's tuple to parameter's.
        final Iterator<PyExpression> subargs_iterator = Arrays.asList(elements).iterator();
        MyParamVisitor visitor = new MyParamVisitor(subargs_iterator, myResult);
        for (PyParameter nested : nested_params) nested.accept(visitor);
        myUnmatchedSubargs.addAll(visitor.getUnmatchedSubargs());
        while (subargs_iterator.hasNext()) {  // more args in a tuple than parameters
          PyExpression overflown_arg = subargs_iterator.next();
          myResult.markArgument(overflown_arg, ArgFlag.IS_UNMAPPED);
        }
      }
      else { // map all what's inside to this arg
        final List<PyNamedParameter> nested_mapped = new ArrayList<PyNamedParameter>(nested_params.length);
        ParamHelper.walkDownParamArray(
          nested_params,
          new ParamHelper.ParamVisitor() {
            @Override public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) {
              nested_mapped.add(param);
            }
          }
        );
        myResult.myNestedMappedParams.put(arg, nested_mapped);
      }
    }

    public void enterNamed(PyNamedParameter param) {
      if (myArgIterator.hasNext()) {
        PyExpression subarg = myArgIterator.next();
        myResult.myPlainMappedParams.put(subarg, param);
      }
      else {
        myResult.myUnmappedParams.add(param);
      }
      // ...and *arg or **arg just won't parse inside a tuple, no need to handle it here
    }
  }
}
