/*
 * 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.
 */
package org.apache.knox.gateway.util.urltemplate;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/*
   Path
     Match
       {path} => {path=*}
       {path=*} // Match single path level. (ie wildcard)
       {path=**} // Match multiple path levels. (ie glob)
       {path=*.ext} // Match single level with simplified regex pattern.
     Expand
       {path} => {path=**} // Note: Default cardinality changes between match and expand.
   Query
     Match
       {queryParam} => {queryParam=*:queryParam}
       {queryParam=*} => {queryParam=*:queryParam} // Match single queryParam value.
       {queryParam=**} => {queryParam=**:queryParam} // Match multiple queryParam values.
       {queryParam=*suffix:other-queryParam}
     Expand
       {queryParam} -> {queryParam=**:queryParam} // Note: Default cardinality changes between match and expand.
       {queryParam=*} -> {queryParam=*:queryParam}
       {queryParam=**} -> {queryParam=**:queryParam}
       {queryParam=other-parm} -> {queryParam=**:otherparam} // Note: Default cardinality changes between match and expand.
       {queryParam=:other-parm} -> {queryParam=**:otherparam} // Note: Default cardinality changes between match and expand.
       {queryParam=*:other-parm} -> {queryParam=*:otherparam}
       {queryParam=**:other-parm} -> {queryParam=**:otherparam}
 */
public class Matcher<V> {

  private Map<Template,V> map;
  private PathNode root;

  public Matcher() {
    map = new LinkedHashMap<>();
    root = new PathNode( null, null );
  }

  public Matcher( Template template, V value ) {
    this();
    add( template, value );
  }

  public V get( Template template ) {
    return map.get( template );
  }

  public void add( Template template, V value ) {
    map.put( template, value );
    PathNode node = root;

    // Add the scheme segment to the tree (if any) while descending.
    node = add( node, template.getScheme() );

    // Add the authority segments (if any) while descending.
    node = add( node, template.getUsername() );
    node = add( node, template.getPassword() );
    node = add( node, template.getHost() );
    node = add( node, template.getPort() );

    // Add the path segments while descending.
    for( Path segment : template.getPath() ) {
      // If the root already contains a matching segment then descend to that pathNode.
      // Otherwise create a child pathNode, addValue it to the root and descend to it.
      // If this new pathNode is a leaf pathNode then set the value.
      node = add( node, segment );
    }

    // Add the fragment (if any) segments while descending.
    // Note: Doing it this way puts the fragment above the query parameters in the match order.
    node = add( node, template.getFragment() );

    if( template.getQuery().isEmpty() && template.getExtra() == null ) {
      // The first template with a value at this node wins.
      if( node.value == null ) {
        node.template = template;
        node.value = value;
      }
    } else {
      // Insert a query pathNode into the tree.
      node.addQuery( template, value );
    }
  }

  private PathNode add( PathNode parent, Segment segment ) {
    PathNode child = parent;
    if( segment != null ) {
      if( ( parent.children != null ) && ( parent.children.containsKey( segment ) ) ) {
        child = parent.children.get( segment );
      } else {
        child = parent.addPath( segment );
      }
    }
    return child;
  }

  public Match match( Template input ) {
    Status status = new Status();
    status.candidates.add( new MatchSegment( null, root, null, null ) );
    boolean matches = true;
    // Separate &= statements for debugability.
    matches &= matchScheme( input, status );
    matches &= matchAuthority( input, status );
    matches &= matchPath( input, status );
    matches &= matchFragment( input, status );
    Match winner;
    if( matches ) {
      winner = pickBestMatch( input, status );
    } else {
      winner = null;
    }
    return winner;
  }

  private boolean matchScheme( Template input, Status status ) {
    pickMatchingChildren( input.getScheme(), status );
    return status.hasCandidates();
  }

  private boolean matchAuthority( Template input, Status status ) {
    pickMatchingChildren( input.getUsername(), status );
    pickMatchingChildren( input.getPassword(), status );
    pickMatchingChildren( input.getHost(), status );
    // port does not makes sense without host
    if(input.getHost() != null) {
      // port is optional, since default ports do not need to present in URL
      pickMatchingOptionalSegment(input.getPort(), status);
    }
    return status.hasCandidates();
  }

  private boolean matchPath( Template input, Status status ) {
    Path segment;
    Iterator<Path> segments = input.getPath().iterator();
    while( segments.hasNext() && status.hasCandidates() ) {
      segment = segments.next();
      pickMatchingChildren( segment, status );
    }
    return status.hasCandidates();
  }

  private boolean matchFragment( Template input, Status status ) {
    pickMatchingChildren( input.getFragment(), status );
    return status.hasCandidates();
  }

  private void pickMatchingChildren( Segment segment, Status status ) {
    if( segment != null ) {
      for( MatchSegment parent : status.candidates ) {
        if( parent.pathNode.hasGlob() ) {
          status.matches.add( new MatchSegment( parent, parent.pathNode, parent.pathNode.segment, segment ) );
        }
        if( parent.pathNode.children != null ) {
          for( PathNode node : parent.pathNode.children.values() ) {
            if( node.matches( segment ) ) {
              status.matches.add( new MatchSegment( parent, node, node.segment, segment ) );
            }
          }
        }
      }
      status.swapMatchesToCandidates();
    }
  }

  /**
   * optional segment, if it does not present (it is null) it is accepted
   */
  private void pickMatchingOptionalSegment( Segment segment, Status status ) {
    for( MatchSegment parent : status.candidates ) {
      if( parent.pathNode.children != null ) {
        for( PathNode node : parent.pathNode.children.values() ) {
          if( segment != null ) {
            if( node.matches( segment ) ) {
              status.matches.add( new MatchSegment( parent, node, node.segment, segment ) );
            }
          } else {
            status.matches.add( new MatchSegment( parent, node, node.segment, segment ) );
          }
        }
      }
    }
    status.swapMatchesToCandidates();
  }

  private Match pickBestMatch( Template input, Status status ) {
    Match bestMatch = new Match( null, null );
    PathNode bestPath = null;
    QueryNode bestQuery = null;
    MatchSegment bestMatchSegment = null;
    for( MatchSegment matchSegment: status.candidates ) {
      PathNode pathNode = matchSegment.pathNode;
      if( ( bestPath == null ) || // If we don't have anything at all pick the pathNode.
          ( pathNode.depth > bestPath.depth ) || // If the pathNode is deeper than the best pathNode, pick it.
          // If the pathNode is the same depth as current best but is static and the best isn't then pick it.
          ( ( pathNode.depth == bestPath.depth ) && ( pathNode.getType() < bestPath.getType() ) ) ) {
        // If the path node has a template then assume we will pick the path node.
        if( pathNode.template != null ) {
          bestPath = pathNode;
          bestQuery = null;
          bestMatch.template = pathNode.template;
          bestMatch.value = pathNode.value;
          bestMatchSegment = matchSegment;
        }
        // If the path node has queries see if one is better match than the path node itself.
        if( pathNode.hasQueries() ) {
          bestQuery = pickBestQueryMatch( input, pathNode );
          if( bestQuery != null && bestQuery.template != null ) {
            bestPath = pathNode;
            bestMatch.template = bestQuery.template;
            bestMatch.value = bestQuery.value;
            bestMatchSegment = matchSegment;
          }
        }
      }
    }
    return createMatch( bestMatchSegment, bestPath, bestQuery, input );
  }

  private QueryNode pickBestQueryMatch( Template input, PathNode pathNode ) {
    QueryNode bestNode = null;
    int bestMatchCount = 0;
    for( QueryNode node : pathNode.queries ) {
      Query extra = node.template.getExtra();
      int nodeQuerySize = node.template.getQuery().size();
      int queryMatchCount = calcQueryMatchCount( node, input );
      boolean matchesNamedQueries = queryMatchCount >= nodeQuerySize;
      boolean matchesExtraQuery =
          ( ( extra == null ) ||
            ( Segment.GLOB_PATTERN.equals( extra.getQueryName() ) ) ||
            ( input.getQuery().size() > nodeQuerySize ) );
      if( ( bestNode == null || queryMatchCount > bestMatchCount ) && ( matchesNamedQueries && matchesExtraQuery ) ) {
        bestMatchCount = queryMatchCount;
        bestNode = node;
      }
    }
    return bestNode;
  }

  private int calcQueryMatchCount( QueryNode node, Template input ) {
    int matchCount = 0;
    Map<String,Query> inputQuery = input.getQuery();
    Map<String,Query> templateQuery = node.template.getQuery();
    for( Query templateSegment : templateQuery.values() ) {
      Query inputSegment = inputQuery.get( templateSegment.getQueryName() );
      if( inputSegment != null && templateSegment.matches( inputSegment ) ) {
        matchCount++ ;
      } else {
        matchCount = 0;
        break;
      }
    }
    return matchCount;
  }

  private Match createMatch( MatchSegment bestMatchSegment, PathNode bestPath, QueryNode bestQuery, Template input ) {
    Match match = null;

    if( bestPath != null ) { //&& ( bestQuery != null || !bestPath.hasQueries() ) ) {

      if( bestQuery != null ) {
        match = new Match( bestQuery.template, bestQuery.value );
      } else {
        match = new Match( bestPath.template, bestPath.value );
      }

      MatchParams matchParams = new MatchParams();

      // Add the matching query segments to the end of the list.
      if( bestQuery != null ) {
        Map<String,Query> inputQuery = input.getQuery();
        for( Query templateSegment : bestQuery.template.getQuery().values() ) {
          Query inputSegment = inputQuery.get( templateSegment.getQueryName() );
          if( inputSegment != null && templateSegment.matches( inputSegment ) ) {
            extractSegmentParams( templateSegment, inputSegment, matchParams );
          }
        }
      }

      // If the template has the "extra" query queryParam then collect query params that were
      // not already matched.
      if( bestQuery != null ) {
        Query extra = bestQuery.template.getExtra();
        if( extra != null ) {
          String paramName = extra.getParamName();
          if( paramName != null && !paramName.isEmpty()) {
            for( Query query: input.getQuery().values() ) {
              String queryName = query.getQueryName();
              if( matchParams.resolve( queryName ) == null ) {
                for( Segment.Value value: query.getValues() ) {
                  matchParams.addValue( queryName, value.getEffectivePattern() );
                }
              }
            }
          }
        }
      }

      // Walk back up the matching segment tree.
      MatchSegment matchSegment = bestMatchSegment;
      while( matchSegment != null && matchSegment.pathNode.depth > 0 ) {
        extractSegmentParams( matchSegment.templateSegment, matchSegment.inputSegment, matchParams );
        matchSegment = matchSegment.parentMatch;
      }
      match.params = matchParams;
    }
    return match;
  }

  private void extractSegmentParams( Segment extractSegment, Segment inputSegment, MatchParams params ) {
    if( extractSegment != null && inputSegment != null ) {
      String paramName = extractSegment.getParamName();
      if(!paramName.isEmpty()) {
        for( Segment.Value value: inputSegment.getValues() ) {
          params.insertValue( paramName, value.getEffectivePattern() );
        }
      }
    }
  }

  private class Status {
    List<MatchSegment> candidates = new ArrayList<>();
    List<MatchSegment> matches = new ArrayList<>();
    List<MatchSegment> temp;

    private void swapMatchesToCandidates() {
      temp = candidates; candidates = matches; matches = temp;
      matches.clear();
    }

    private boolean hasCandidates() {
      return !candidates.isEmpty();
    }
  }

  private class MatchSegment {
    private MatchSegment parentMatch;
    private PathNode pathNode;
    private Segment templateSegment;
    private Segment inputSegment;

    MatchSegment( MatchSegment parent, PathNode node, Segment templateSegment, Segment inputSegment ) {
      this.parentMatch = parent;
      this.pathNode = node;
      this.templateSegment = templateSegment;
      this.inputSegment = inputSegment;
    }
  }

  private class MatchParams implements Params {

    private Map<String,List<String>> map = new LinkedHashMap<>();

    @Override
    public Set<String> getNames() {
      return map.keySet();
    }

    private List<String> getOrAddValues( String name ) {
      List<String> values = resolve( name );
      if( values == null ) {
        values = new ArrayList<>( 1 );
        map.put( name, values );
      }
      return values;
    }

    public void addValue( String name, String value ) {
      List<String> values = getOrAddValues( name );
      values.add( value );
    }

    public void insertValue( String name, String value ) {
      List<String> values = getOrAddValues( name );
      values.add( 0, value );
    }

    @Override
    public List<String> resolve( String name ) {
      return map.get( name );
    }

  }

  public class Match {
    private Template template;
    private V value;
    private Params params;
    //TODO private Params extra;

    Match( Template template, V value ) {
      this.template = template;
      this.value = value;
    }

    public Template getTemplate() {
      return template;
    }

    public V getValue() {
      return value;
    }

    public Params getParams() {
      return params;
    }
  }

  private class PathNode extends Node {

    int depth; // Zero based depth of the pathNode for "best pathNode" calculation.
    Segment segment;
    Map<Segment,PathNode> children;
    Set<QueryNode> queries;

    PathNode( PathNode parent, Segment segment ) {
      super( null, null );
      this.depth = ( parent == null ) ? 0 : parent.depth+1;
      this.segment = segment;
      this.children = null;
      this.queries = null;
    }

    private PathNode addPath( Segment path ) {
      if( children == null ) {
        children = new LinkedHashMap<>();
      }
      PathNode child = new PathNode( this, path );
      children.put( path, child );
      return child;
    }

    private QueryNode addQuery( Template template, V value ) {
      if( queries == null ) {
        queries = new LinkedHashSet<>();
      }
      QueryNode query = new QueryNode( template, value );
      queries.add( query );
      return query;
    }

    private int getType() {
      int type = Segment.UNKNOWN;
      if( segment != null ) {
        for( Segment.Value value: segment.getValues() ) {
          int vType = value.getType();
          type = type < vType ? type : vType;
          if( type == Segment.STATIC ) {
            break;
          }
        }
      }
      return type;
    }

    private boolean hasGlob() {
      boolean is = false;
      if( segment != null ) {
        for( Segment.Value value: segment.getValues() ) {
          if( Segment.GLOB == value.getType() ) {
            is = true;
          }
        }
      }
      return is;
    }

    private boolean hasQueries() {
      return( queries != null && !queries.isEmpty() );
    }

    private boolean matches( Segment segment ) {
      return( this.segment.matches( segment ) );
    }

  }

  private class QueryNode extends Node {
    QueryNode( Template template, V value ) {
      super( template, value );
    }
  }

  private class Node {
    Template template;
    V value;

    Node( Template template, V value ) {
      this.template = template;
      this.value = value;
    }
  }
}
