// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// This program and the accompanying materials are made available
// under the terms of the Eclipse Public License v2.0 which accompanies
// this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html

package org.eclipse.wst.jsdt.chromium.debug.core.sourcemap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import junit.framework.Assert;

import org.eclipse.wst.jsdt.chromium.debug.core.model.StringMappingData;
import org.eclipse.wst.jsdt.chromium.debug.core.model.VmResourceId;
import org.eclipse.wst.jsdt.chromium.debug.core.sourcemap.SourcePositionMap.TranslateDirection;
import org.eclipse.wst.jsdt.chromium.debug.core.sourcemap.SourcePositionMapBuilder.CannotAddException;
import org.eclipse.wst.jsdt.chromium.debug.core.sourcemap.SourcePositionMapBuilder.MappingHandle;
import org.eclipse.wst.jsdt.chromium.debug.core.sourcemap.SourcePositionMapBuilder.ResourceSection;
import org.junit.Test;

public class PositionMapBuilderImplTest {
  /**
   * Creates a sample position map and checks several points.
   */
  @Test
  public void basicTest() throws CannotAddException {
    SourcePositionMapBuilder builder = new PositionMapBuilderImpl();
    builder.addMapping(new ResourceSection(new VmResourceId("source1.js", null), 0, 0, 5, 0),
        new ResourceSection(new VmResourceId("compiled.js", null), 0, 0, 1, 0),
        new TextSectionMappingImpl(
            new StringMappingData(new int [] { 0,0, 1,0,  2,0,  3,0,  4,0 } , 5, 0),
            new StringMappingData(new int [] { 0,0, 0,10, 0,20, 0,30, 0,40 }, 0, 50)));

    builder.addMapping(new ResourceSection(new VmResourceId("source2.js", null), 0, 0, 5, 0),
        new ResourceSection(new VmResourceId("compiled.js", null), 1, 0, 2, 0),
        new TextSectionMappingImpl(
            new StringMappingData(new int [] { 0,0, 1,0,  2,0,  3,0,  4,0}, 5, 0),
            new StringMappingData(new int [] { 1,0, 1,10, 1,20, 1,30, 1,40}, 1, 50)));

    builder.addMapping(new ResourceSection(new VmResourceId("source3.js", null), 0, 0, 5, 0),
        new ResourceSection(new VmResourceId("compiled.js", null), 2, 0, 3, 0),
        new TextSectionMappingImpl(
            new StringMappingData(new int [] {0,0, 1,0,  2,0,  3,0,  4,0}, 5, 0),
            new StringMappingData(new int [] {2,0, 2,10, 2,20, 2,30, 2,40}, 2, 50)));

    SourcePositionMap map = builder.getSourcePositionMap();

    checkTwoWay(map, "other.js", 17, 4, "other.js", 17, 4, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 2, 11, "source3.js", 1, 1, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 0, 0, "source1.js", 0, 0, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 0, 1, "source1.js", 0, 1, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 1, 0, "source2.js", 0, 0, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 1, 3, "source2.js", 0, 3, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 2, 0, "source3.js", 0, 0, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 2, 3, "source3.js", 0, 3, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 3, 0, "compiled.js", 3, 0, TranslateDirection.VM_TO_USER);

    checkTwoWay(map, "compiled.js", 3, 3, "compiled.js", 3, 3, TranslateDirection.VM_TO_USER);
  }

  private static SourcePosition checkOneWay(SourcePositionMap map,
      String fromFile, int fromLine, int fromColumn,
      String toFile, int toLine, int toColumn, TranslateDirection direction) {
    SourcePosition result = map.translatePosition(new VmResourceId(fromFile, null),
        fromLine, fromColumn, direction);
    Assert.assertEquals(new SourcePosition(new VmResourceId(toFile, null), toLine, toColumn),
        result);
    return result;
  }

  private static void checkTwoWay(SourcePositionMap map,
      String fromFile, int fromLine, int fromColumn,
      String toFile, int toLine, int toColumn, TranslateDirection direction) {
    checkOneWay(map, fromFile, fromLine, fromColumn, toFile, toLine, toColumn, direction);
    SourcePosition result = map.translatePosition(new VmResourceId(toFile, null), toLine, toColumn,
        direction.opposite());
    Assert.assertEquals(new SourcePosition(new VmResourceId(fromFile, null), fromLine, fromColumn),
        result);
  }

  /**
   * Checks that {@link SourcePositionMapBuilder#addMapping} correctly handles overlapping regions.
   */
  @Test
  public void testAddMappingOverlaps() throws CannotAddException {
    new OverlappingMapTestFramework().run();
  }

  private static abstract class MultiRangeMapTestFrameworkBase {
    static final VmResourceId COMPILED_JS_ID = new VmResourceId("compiled.js", null);
    static ResourceSection[] GOOD_SECTIONS = {
      new ResourceSection(COMPILED_JS_ID, 1, 0, 2, 0),
      new ResourceSection(COMPILED_JS_ID, 3, 0, 3, 0),
      new ResourceSection(COMPILED_JS_ID, 5, 0, 5, 0),
      new ResourceSection(COMPILED_JS_ID, 5, 0, 5, 0),
      new ResourceSection(COMPILED_JS_ID, 5, 0, 8, 0),
      new ResourceSection(COMPILED_JS_ID, 8, 0, 8, 0),
    };
    private static final int SHUFFLE_TRIES = 10;

    void run() throws CannotAddException {
      // We get all good sections and add them in a random order. Then we check
      // that each of conflict section will not add.

      Random random = new Random(0);
      for (int i = 0; i < SHUFFLE_TRIES; i++) {
        runOneShuffle(random);
      }
    }

    protected abstract void runOneShuffle(Random random) throws CannotAddException;

    protected ArrayList<MappingHandle> addGoodRanges(SourcePositionMapBuilder builder,
        Random random) throws CannotAddException {
      List<ResourceSection> vmSections =
          new ArrayList<SourcePositionMapBuilder.ResourceSection>(Arrays.asList(GOOD_SECTIONS));
      Collections.shuffle(vmSections, random);
      ArrayList<MappingHandle> result =
          new ArrayList<SourcePositionMapBuilder.MappingHandle>(vmSections.size());
      // Add all good sections.
      int index = 0;
      for (ResourceSection section : vmSections) {
        addSection(builder, section, index);
        index++;
      }
      return result;
    }

    protected static MappingHandle addSection(SourcePositionMapBuilder builder,
        ResourceSection vmSection, int index) throws CannotAddException {
      ResourceSection originalSection =
          new ResourceSection(new VmResourceId(("source" + index + ".js"), null), 0, 0, 5, 0);

      TextSectionMappingImpl textMapping = new TextSectionMappingImpl(
          new StringMappingData(
              new int [] { vmSection.getStart().getLine(), vmSection.getStart().getColumn() },
              vmSection.getEnd().getLine(), vmSection.getEnd().getColumn()),
          new StringMappingData((new int [] { 0, 0 }), 5, 0));

      return builder.addMapping(originalSection, vmSection, textMapping);
    }
  }

  private static class OverlappingMapTestFramework extends MultiRangeMapTestFrameworkBase {
    private static ResourceSection[] CONFLICT_SECTIONS = {
      new ResourceSection(COMPILED_JS_ID, 1, 0, 2, 0),
      new ResourceSection(COMPILED_JS_ID, 0, 1, 1, 1),
      new ResourceSection(COMPILED_JS_ID, 1, 1, 2, 1),
      new ResourceSection(COMPILED_JS_ID, 1, 1, 1, 2),
      new ResourceSection(COMPILED_JS_ID, 2, 0, 4, 0),
      new ResourceSection(COMPILED_JS_ID, 4, 0, 6, 0),
      new ResourceSection(COMPILED_JS_ID, 6, 0, 7, 0),
      new ResourceSection(COMPILED_JS_ID, 7, 0, 9, 0),
    };

    protected void runOneShuffle(Random random) throws CannotAddException {

      final SourcePositionMapBuilder builder = new PositionMapBuilderImpl();

      List<MappingHandle> goodRangeHandles = addGoodRanges(builder, random);

      final int conflict_section_index = goodRangeHandles.size();
      // Now try to add conflict sections.
      for (final ResourceSection section : CONFLICT_SECTIONS) {
        assertThrowsAddException(new RunnableWithCannotAddException() {
          public void run() throws CannotAddException {
            addSection(builder, section, conflict_section_index);
          }
        });
      }
    }
  }

  /**
   * Checks that {@link SourcePositionMapBuilder} can add mappings and delete them
   * in different order.
   */
  @Test
  public void testAddAndDeleteMapping() throws CannotAddException {
    new AddAndDeleteMapTestFramework().run();
  }

  private static class AddAndDeleteMapTestFramework extends MultiRangeMapTestFrameworkBase {
    protected void runOneShuffle(Random random) throws CannotAddException {
      final SourcePositionMapBuilder builder = new PositionMapBuilderImpl();

      ArrayList<MappingHandle> goodRangeHandles = addGoodRanges(builder, random);

      // Delete ranges in other order.
      Collections.shuffle(goodRangeHandles, random);

      for (MappingHandle handle : goodRangeHandles) {
        handle.delete();
      }
    }
  }

  private interface RunnableWithCannotAddException {
    void run() throws CannotAddException;
  }

  private static void assertThrowsAddException(RunnableWithCannotAddException runnable) {
    try {
      runnable.run();
      Assert.fail("Exception expected");
    } catch (CannotAddException e) {
      // Expected exception.
    }
  }
}
