/*
 * 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.solr.search;

import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.lucene.search.Query;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.join.CrossCollectionJoinQParser;
import org.apache.solr.search.join.ScoreJoinQParserPlugin;
import org.apache.solr.util.RefCounted;

public class JoinQParserPlugin extends QParserPlugin {

  public static final String NAME = "join";
  /** Choose the internal algorithm */
  private static final String METHOD = "method";

  private String routerField;

  private Set<String> allowSolrUrls;

  private static class JoinParams {
    final String fromField;
    final String fromCore;
    final Query fromQuery;
    final long fromCoreOpenTime;
    final String toField;

    public JoinParams(String fromField, String fromCore, Query fromQuery, long fromCoreOpenTime, String toField) {
      this.fromField = fromField;
      this.fromCore = fromCore;
      this.fromQuery = fromQuery;
      this.fromCoreOpenTime = fromCoreOpenTime;
      this.toField = toField;
    }
  }

  private enum Method {
    index {
      @Override
      Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
        final JoinParams jParams = parseJoin(qparser);
        final JoinQuery q = new JoinQuery(jParams.fromField, jParams.toField, jParams.fromCore, jParams.fromQuery);
        q.fromCoreOpenTime = jParams.fromCoreOpenTime;
        return q;
      }

      @Override
      Query makeJoinDirectFromParams(JoinParams jParams) {
        return new JoinQuery(jParams.fromField, jParams.toField, null, jParams.fromQuery);
      }
    },
    dvWithScore {
      @Override
      Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
        return new ScoreJoinQParserPlugin().createParser(qparser.qstr, qparser.localParams, qparser.params, qparser.req).parse();
      }

      @Override
      Query makeJoinDirectFromParams(JoinParams jParams) {
        return ScoreJoinQParserPlugin.createJoinQuery(jParams.fromQuery, jParams.fromField, jParams.toField, ScoreMode.None);
      }
    },
    topLevelDV {
      @Override
      Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
        final JoinParams jParams = parseJoin(qparser);
        final JoinQuery q = new TopLevelJoinQuery(jParams.fromField, jParams.toField, jParams.fromCore, jParams.fromQuery);
        q.fromCoreOpenTime = jParams.fromCoreOpenTime;
        return q;
      }

      @Override
      Query makeJoinDirectFromParams(JoinParams jParams) {
        return new TopLevelJoinQuery(jParams.fromField, jParams.toField, null, jParams.fromQuery);
      }
    },
    crossCollection {
      @Override
      Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError {
        return new CrossCollectionJoinQParser(qparser.qstr, qparser.localParams, qparser.params, qparser.req,
                plugin.routerField, plugin.allowSolrUrls).parse();
      }
    };

    abstract Query makeFilter(QParser qparser, JoinQParserPlugin plugin) throws SyntaxError;

    Query makeJoinDirectFromParams(JoinParams jParams) {
      throw new IllegalStateException("Join method [" + name() + "] doesn't support qparser-less creation");
    }

    JoinParams parseJoin(QParser qparser) throws SyntaxError {
      final String fromField = qparser.getParam("from");
      final String fromIndex = qparser.getParam("fromIndex");
      final String toField = qparser.getParam("to");
      final String v = qparser.localParams.get(QueryParsing.V);
      final String coreName;

      Query fromQuery;
      long fromCoreOpenTime = 0;

      if (fromIndex != null && !fromIndex.equals(qparser.req.getCore().getCoreDescriptor().getName()) ) {
        CoreContainer container = qparser.req.getCore().getCoreContainer();

        // if in SolrCloud mode, fromIndex should be the name of a single-sharded collection
        coreName = ScoreJoinQParserPlugin.getCoreName(fromIndex, container);

        final SolrCore fromCore = container.getCore(coreName);
        if (fromCore == null) {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
              "Cross-core join: no such core " + coreName);
        }

        RefCounted<SolrIndexSearcher> fromHolder = null;
        LocalSolrQueryRequest otherReq = new LocalSolrQueryRequest(fromCore, qparser.params);
        try {
          QParser parser = QParser.getParser(v, otherReq);
          fromQuery = parser.getQuery();
          fromHolder = fromCore.getRegisteredSearcher();
          if (fromHolder != null) fromCoreOpenTime = fromHolder.get().getOpenNanoTime();
        } finally {
          otherReq.close();
          fromCore.close();
          if (fromHolder != null) fromHolder.decref();
        }
      } else {
        coreName = null;
        QParser fromQueryParser = qparser.subQuery(v, null);
        fromQueryParser.setIsFilter(true);
        fromQuery = fromQueryParser.getQuery();
      }

      final String indexToUse = coreName == null ? fromIndex : coreName;
      return new JoinParams(fromField, indexToUse, fromQuery, fromCoreOpenTime, toField);
    }
  }

  @Override
  @SuppressWarnings({"unchecked"})
  public void init(@SuppressWarnings({"rawtypes"})NamedList args) {
    routerField = (String) args.get("routerField");

    if (args.get("allowSolrUrls") != null) {
      allowSolrUrls = new HashSet<>();
      allowSolrUrls.addAll((List<String>) args.get("allowSolrUrls"));
    } else {
      allowSolrUrls = null;
    }
  }

  @Override
  public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
    final JoinQParserPlugin plugin = this;

    return new QParser(qstr, localParams, params, req) {

      @Override
      public Query parse() throws SyntaxError {
        if (localParams != null && localParams.get(METHOD) != null) {
          // TODO Make sure 'method' is valid value here and give users a nice error
          final Method explicitMethod = Method.valueOf(localParams.get(METHOD));
          return explicitMethod.makeFilter(this, plugin);
        }

        // Legacy join behavior before introduction of SOLR-13892
        if(localParams!=null && localParams.get(ScoreJoinQParserPlugin.SCORE)!=null) {
          return new ScoreJoinQParserPlugin().createParser(qstr, localParams, params, req).parse();
        } else {
          return Method.index.makeFilter(this, plugin);
        }
      }
    };
  }

  private static final EnumSet<Method> JOIN_METHOD_WHITELIST = EnumSet.of(Method.index, Method.topLevelDV, Method.dvWithScore);
  /**
   * A helper method for other plugins to create (non-scoring) JoinQueries wrapped around arbitrary queries against the same core.
   * 
   * @param subQuery the query to define the starting set of documents on the "left side" of the join
   * @param fromField "left side" field name to use in the join
   * @param toField "right side" field name to use in the join
   * @param method indicates which implementation should be used to process the join.  Currently only 'index',
   *               'dvWithScore', and 'topLevelDV' are supported.
   */
  public static Query createJoinQuery(Query subQuery, String fromField, String toField, String method) {
    // no method defaults to 'index' for back compatibility
    if ( method == null ) {
      return new JoinQuery(fromField, toField, null, subQuery);
    }


    final Method joinMethod = parseMethodString(method);
    if (! JOIN_METHOD_WHITELIST.contains(joinMethod)) {
      // TODO Throw something that the callers here (FacetRequest) can catch and produce a more domain-appropriate error message for?
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
          "Join method " + method + " not supported for non-scoring, same-core joins");
    }

    final JoinParams jParams = new JoinParams(fromField, null, subQuery, 0L, toField);
    return joinMethod.makeJoinDirectFromParams(jParams);
  }

  private static Method parseMethodString(String method) {
    try {
      return Method.valueOf(method);
    } catch (IllegalArgumentException iae) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Provided join method '" + method + "' not supported");
    }
  }
  
}