/*
 * Copyright (c) 2014, Oracle America, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *  * Neither the name of Oracle nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.hubspot.jinjava.benchmarks.liquid;

import static org.apache.commons.io.FileUtils.listFiles;
import static org.apache.commons.io.FileUtils.readFileToString;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import ch.qos.logback.classic.Level;

import com.google.common.base.Charsets;
import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.tree.Node;

@State(Scope.Benchmark)
public class LiquidBenchmark {
  
  public List<String> templates;
  public Map<String, ?> bindings;
  
  public Jinjava jinjava;
  
  @SuppressWarnings("unchecked")
  @Setup
  public void setup() throws IOException {
    ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
    logger.setLevel(Level.WARN);
    
    jinjava = new Jinjava();

    jinjava.getGlobalContext().registerClasses(
        Filters.OverrideDateFilter.class,
        
        Filters.JsonFilter.class,
        Filters.LinkToAddTagFilter.class,
        Filters.LinkToRemoveTagFilter.class,
        Filters.LinkToTagFilter.class,
        Filters.HighlightActiveTagFilter.class,
        Filters.MoneyFilter.class,
        Filters.MoneyWithCurrencyFilter.class,
        Filters.ShopAssetUrlFilter.class,
        Filters.ShopGlobalAssetUrl.class,
        Filters.ShopImgTagFilter.class,
        Filters.ShopLinkTo.class,
        Filters.ShopScriptTag.class,
        Filters.ShopShopifyAssetUrl.class,
        Filters.ShopStylesheetTag.class,
        Filters.WeightFilter.class,
        Filters.WeightWithUnitFilter.class,
        
        Tags.AssignTag.class,
        Tags.CommentFormTag.class,
        Tags.PaginateTag.class,
        Tags.TableRowTag.class
    );
    
    templates = new ArrayList<>();
    
    Map<String, ?> db = (Map<String, ?>) new Yaml().load(readFileToString(new File("liquid/performance/shopify/vision.database.yml"), Charsets.UTF_8));
    bindings = new HashMap<>(db);
    
    File baseDir = new File("liquid/performance/tests");
    for(File tmpl : listFiles(baseDir, new String[]{"liquid"}, true)){
      
      String template = readFileToString(tmpl, Charsets.UTF_8);
      // convert filter syntax from ':' to '()'
      template = template.replaceAll("\\| ([\\w_]+): (.*?)(\\||})", "| $1($2)$3");
      // jinjava doesn't have the '?' postfix binary operator
      template = template.replaceAll("if (.*?)\\?", "if $1");
      // no support for offset:n
      template = template.replaceAll("offset:\\s*\\d*", "");
      // no support for limit:n
      template = template.replaceAll("limit:\\s*\\d*", "");
      // no support for cols:n
      template = template.replaceAll("cols:\\s*\\d*", "");
      // no support for for reversal
      template = template.replaceAll(" reversed", "");
      
      // System.out.println("Adding template: " + tmpl.getAbsolutePath());
      // System.out.println(template);

      templates.add(template);
    }
  }
  
  @Benchmark
  public void parse(Blackhole blackhole) {
    JinjavaInterpreter interpreter = new JinjavaInterpreter(jinjava, jinjava.getGlobalContext(), jinjava.getGlobalConfig());

    for(String template : templates) {
      Node parsed = interpreter.parse(template);
      if(blackhole != null) {
        blackhole.consume(parsed);
      }
    }
  }
  
  @Benchmark
  public void parseAndRender(Blackhole blackhole) {
    for(String template : templates) {
      String result = jinjava.render(template, bindings);
      if(blackhole != null) {
        blackhole.consume(result);
      }
    }
  }
  
  public static void main(String[] args) throws Exception {
    LiquidBenchmark b = new LiquidBenchmark();
    b.setup();
    b.parse(null);
    b.parseAndRender(null);
  }

}

@@ -1,1583 +1,4 @@
-/*%0A * Copyright (c) 2014, Oracle America, Inc.%0A * All rights reserved.%0A *%0A * Redistribution and use in source and binary forms, with or without%0A * modification, are permitted provided that the following conditions are met:%0A *%0A *  * Redistributions of source code must retain the above copyright notice,%0A *    this list of conditions and the following disclaimer.%0A *%0A *  * Redistributions in binary form must reproduce the above copyright%0A *    notice, this list of conditions and the following disclaimer in the%0A *    documentation and/or other materials provided with the distribution.%0A *%0A *  * Neither the name of Oracle nor the names of its contributors may be used%0A *    to endorse or promote products derived from this software without%0A *    specific prior written permission.%0A *%0A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS %22AS IS%22%0A * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE%0A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE%0A * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE%0A * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR%0A * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF%0A * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS%0A * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN%0A * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)%0A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF%0A * THE POSSIBILITY OF SUCH DAMAGE.%0A */%0A%0A
 pack

Update LiquidBenchmark.java