/*
 * 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.update.processor;

import static org.apache.solr.update.processor.DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM;

import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.core.SolrCore;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.SolrTestCaseJ4;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 */
public class UpdateRequestProcessorFactoryTest extends SolrTestCaseJ4 {

  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  @BeforeClass
  public static void beforeClass() throws Exception {
    System.setProperty("enable.runtime.lib", "true");
    initCore("solrconfig-transformers.xml", "schema.xml");
  }

  public void testRequestTimeUrp(){
    SolrCore core = h.getCore();
    ModifiableSolrParams params = new ModifiableSolrParams()
        .add("processor", "template")
        .add("template.field", "id_t:{firstName}_{lastName}")
        .add("template.field", "another_t:{lastName}_{firstName}")
        .add("template.field", "missing_t:{lastName}_{unKnown}");
    UpdateRequestProcessorChain chain = core.getUpdateProcessorChain(params);
    List<UpdateRequestProcessorFactory> l = chain.getProcessors();
    assertTrue(l.get(0) instanceof TemplateUpdateProcessorFactory);


  }
  
  public void testConfiguration() throws Exception 
  {
    SolrCore core = h.getCore();

    // make sure it loaded the factories
    UpdateRequestProcessorChain chained = core.getUpdateProcessingChain( "standard" );
    
    // Make sure it got 3 items (4 configured, 1 is enable=false)
    assertEquals("wrong number of (enabled) factories in chain",
                 3, chained.getProcessors().size() );

    // first one should be log, and it should be configured properly
    UpdateRequestProcessorFactory first = chained.getProcessors().get(0);
    assertEquals("wrong factory at front of chain",
                 LogUpdateProcessorFactory.class, first.getClass());
    LogUpdateProcessorFactory log = (LogUpdateProcessorFactory)first;
    assertEquals("wrong config for LogUpdateProcessorFactory.maxNumToLog",
                 100, log.maxNumToLog );
    assertEquals("wrong config for LogUpdateProcessorFactory.slowUpdateThresholdMillis",
                 2000, log.slowUpdateThresholdMillis);


    UpdateRequestProcessorChain custom = core.getUpdateProcessingChain( null );
    CustomUpdateRequestProcessorFactory link = (CustomUpdateRequestProcessorFactory) custom.getProcessors().get(0);
    
    assertEquals( custom, core.getUpdateProcessingChain( "" ) );
    assertEquals( custom, core.getUpdateProcessingChain( "custom" ) );
    
    // Make sure the NamedListArgs got through ok
    assertEquals( "{name={n8=88,n9=99}}", link.args.toString() );
  }

  public void testUpdateDistribChainSkipping() throws Exception {

    // a key part of this test is verifying that LogUpdateProcessor is found in all chains because it
    // is a @RunAlways processor -- but in order for that to work, we have to sanity check that the log
    // level is at least "INFO" otherwise the factory won't even produce a processor and all our assertions
    // are for nought.  (see LogUpdateProcessorFactory.getInstance)
    //
    // TODO: maybe create a new mock Processor w/ @RunAlways annot if folks feel requiring INFO is evil.
    assertTrue("Tests must be run with INFO level logging "+
               "otherwise LogUpdateProcessor isn't used and can't be tested.", log.isInfoEnabled());
    
    final int EXPECTED_CHAIN_LENGTH = 5;
    SolrCore core = h.getCore();
    for (final String name : Arrays.asList("distrib-chain-explicit",
                                           "distrib-chain-implicit",
                                           "distrib-chain-noop")) {

      UpdateRequestProcessor proc;
      List<UpdateRequestProcessor> procs;
      
      UpdateRequestProcessorChain chain = core.getUpdateProcessingChain(name);
      assertNotNull(name, chain);

      // either explicitly, or because of injection
      assertEquals(name + " factory chain length: " + chain.toString(), EXPECTED_CHAIN_LENGTH,
                   chain.getProcessors().size());

      // test a basic (non distrib) chain
      proc = chain.createProcessor(req(), new SolrQueryResponse());
      procs = procToList(proc);

      int expectedProcLen = EXPECTED_CHAIN_LENGTH;
      if ("distrib-chain-noop".equals(name)) { // NoOpDistributingUpdateProcessorFactory produces no processor
        expectedProcLen--;
      }
      if (procs.stream().anyMatch(p -> p.getClass().getSimpleName().equals("NestedUpdateProcessor"))) {
        expectedProcLen++; // NestedUpdate sneaks in via RunUpdate's Factory.
      }

      assertEquals(name + " procs size: " + procs.toString(), expectedProcLen, procs.size());
      
      // Custom comes first in all three of our chains
      assertTrue(name + " first processor isn't a CustomUpdateRequestProcessor: " + procs.toString(),
                 ( // compare them both just because i'm going insane and the more checks the better
                   proc instanceof CustomUpdateRequestProcessor
                   && procs.get(0) instanceof CustomUpdateRequestProcessor));

      // Log should always come second in our chain.
      assertNotNull(name + " proc.next is null", proc.next);
      assertNotNull(name + " second proc is null", procs.get(1));

      assertTrue(name + " second proc isn't LogUpdateProcessor: " + procs.toString(),
                 ( // compare them both just because i'm going insane and the more checks the better
                   proc.next instanceof LogUpdateProcessorFactory.LogUpdateProcessor
                   && procs.get(1) instanceof LogUpdateProcessorFactory.LogUpdateProcessor));

      // fetch the distributed version of this chain
      proc = chain.createProcessor(req(DISTRIB_UPDATE_PARAM, "NONE"), // just some non-blank value
                                   new SolrQueryResponse());
      procs = procToList(proc);
      assertNotNull(name + " (distrib) chain produced null proc", proc);
      assertFalse(name + " (distrib) procs is empty", procs.isEmpty());

      // for these 3 (distrib) chains, the first proc should always be LogUpdateProcessor
      assertTrue(name + " (distrib) first proc should be LogUpdateProcessor because of @RunAlways: "
                 + procs.toString(),
                 ( // compare them both just because i'm going insane and the more checks the better
                   proc instanceof LogUpdateProcessorFactory.LogUpdateProcessor
                   && procs.get(0) instanceof LogUpdateProcessorFactory.LogUpdateProcessor));

      // for these 3 (distrib) chains, the last proc should always be RunUpdateProcessor
      assertTrue(name + " (distrib) last processor isn't a RunUpdateProcessor: " + procs.toString(),
                 procs.get(procs.size()-1) instanceof RunUpdateProcessorFactory.RunUpdateProcessor );

      // either 1 proc was droped in distrib mode, or 1 for the "implicit" chain

      expectedProcLen = EXPECTED_CHAIN_LENGTH;
      expectedProcLen--; // -1 = all chains lose CustomUpdateRequestProcessorFactory
      if ("distrib-chain-explicit".equals(name) == false) {
        // -1 = distrib-chain-noop: NoOpDistributingUpdateProcessorFactory produces no processor
        // -1 = distrib-chain-implicit: does RemoveBlank before distrib
        expectedProcLen--;
      }
      if (procs.stream().anyMatch(p -> p.getClass().getSimpleName().equals("NestedUpdateProcessor"))) {
        expectedProcLen++; // NestedUpdate sneaks in via RunUpdate's Factory.
      }
      assertEquals(name + " (distrib) chain has wrong length: " + procs.toString(),
          expectedProcLen, procs.size());
    }

  }

  /**
   * walks the "next" values of the proc building up a List of the procs for easier testing
   */
  public static List<UpdateRequestProcessor> procToList(UpdateRequestProcessor proc) {
    List<UpdateRequestProcessor> result = new ArrayList<>(7);
    while (null != proc) {
      result.add(proc);
      proc = proc.next;
    }
    return result;
  }
}

