// Copyright 2008 The Closure Library Authors. All Rights Reserved.
// Use of this source code is governed by the Apache License, Version 2.0.

goog.provide('goog.graphics.PathTest');
goog.setTestOnly('goog.graphics.PathTest');

goog.require('goog.array');
goog.require('goog.math');
goog.require('goog.graphics.Path');
goog.require('goog.graphics.AffineTransform');
goog.require('goog.testing.graphics');
goog.require('goog.testing.jsunit');

function testConstructor() {
  var path = new goog.graphics.Path();
  assertTrue(path.isSimple());
  assertNull(path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals([], path);
}


function testGetSegmentCount() {
  assertArrayEquals([2, 2, 6, 6, 0], goog.array.map([
    goog.graphics.Path.Segment.MOVETO,
    goog.graphics.Path.Segment.LINETO,
    goog.graphics.Path.Segment.CURVETO,
    goog.graphics.Path.Segment.ARCTO,
    goog.graphics.Path.Segment.CLOSE
  ], goog.graphics.Path.getSegmentCount));
}


function testSimpleMoveTo() {
  var path = new goog.graphics.Path();
  path.moveTo(30, 50);
  assertTrue(path.isSimple());
  assertObjectEquals([30, 50], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 30, 50], path);
}


function testRepeatedMoveTo() {
  var path = new goog.graphics.Path();
  path.moveTo(30, 50);
  path.moveTo(40, 60);
  assertTrue(path.isSimple());
  assertObjectEquals([40, 60], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 40, 60], path);
}


function testSimpleLineTo() {
  var path = new goog.graphics.Path();
  var e = assertThrows(function() {
    path.lineTo(30, 50);
  });
  assertEquals('Path cannot start with lineTo', e.message);
  path.moveTo(0, 0);
  path.lineTo(30, 50);
  assertTrue(path.isSimple());
  assertObjectEquals([30, 50], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50], path);
}


function testMultiArgLineTo() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.lineTo(30, 50, 40 , 60);
  assertTrue(path.isSimple());
  assertObjectEquals([40, 60], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60],
      path);
}


function testRepeatedLineTo() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.lineTo(30, 50);
  path.lineTo(40, 60);
  assertTrue(path.isSimple());
  assertObjectEquals([40, 60], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60],
      path);
}


function testSimpleCurveTo() {
  var path = new goog.graphics.Path();
  var e = assertThrows(function() {
    path.curveTo(10, 20, 30, 40, 50, 60);
  });
  assertEquals('Path cannot start with curve', e.message);
  path.moveTo(0, 0);
  path.curveTo(10, 20, 30, 40, 50, 60);
  assertTrue(path.isSimple());
  assertObjectEquals([50, 60], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(
      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60], path);
}


function testMultiCurveTo() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.curveTo(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120);
  assertTrue(path.isSimple());
  assertObjectEquals([110, 120], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(
      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
      path);
}


function testRepeatedCurveTo() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.curveTo(10, 20, 30, 40, 50, 60);
  path.curveTo(70, 80, 90, 100, 110, 120);
  assertTrue(path.isSimple());
  assertObjectEquals([110, 120], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(
      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
      path);
}


function testSimpleArc() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  assertFalse(path.isSimple());
  var p = path.getCurrentPoint();
  assertEquals(55, p[0]);
  assertRoughlyEquals(77.32, p[1], 0.01);
  goog.testing.graphics.assertPathEquals(
      ['M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32], path);
}


function testArcNonConnectClose() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.arc(10, 10, 10, 10, -90, 180);
  assertObjectEquals([10, 20], path.getCurrentPoint());
  path.close();
  assertObjectEquals([10, 0], path.getCurrentPoint());
}


function testRepeatedArc() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  path.arc(50, 60, 10, 20, 60, 30, false);
  assertFalse(path.isSimple());
  assertObjectEquals([50, 80], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'A', 10, 20, 30, 30, 55, 77.32,
      'M', 55, 77.32,
      'A', 10, 20, 60, 30, 50, 80], path);
}


function testRepeatedArc2() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  path.arc(50, 60, 10, 20, 60, 30, true);
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'A', 10, 20, 30, 30, 55, 77.32,
      'A', 10, 20, 60, 30, 50, 80], path);
}


function testCompleteCircle() {
  var path = new goog.graphics.Path();
  path.arc(0, 0, 10, 10, 0, 360, false);
  assertFalse(path.isSimple());
  var p = path.getCurrentPoint();
  assertRoughlyEquals(10, p[0], 0.01);
  assertRoughlyEquals(0, p[1], 0.01);
  goog.testing.graphics.assertPathEquals(
      ['M', 10, 0, 'A', 10, 10, 0, 360, 10, 0], path);
}


function testClose() {
  var path = new goog.graphics.Path();
  try {
    path.close();
    fail();
  } catch (e) {
    // Expected
    assertEquals('Path cannot start with close', e.message);
  }
  path.moveTo(0, 0);
  path.lineTo(10, 20, 30, 40, 50, 60);
  path.close()
  assertTrue(path.isSimple());
  assertObjectEquals([0, 0], path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals(
      ['M', 0, 0, 'L', 10, 20, 30, 40, 50, 60, 'X'], path);
}


function testClear() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.arc(50, 60, 10, 20, 30, 30, false);
  path.clear();
  assertTrue(path.isSimple());
  assertNull(path.getCurrentPoint());
  goog.testing.graphics.assertPathEquals([], path);
}


function testCreateSimplifiedPath() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.arc(50, 60, 10, 20, 30, 30, false);
  assertFalse(path.isSimple());
  path = goog.graphics.Path.createSimplifiedPath(path);
  assertTrue(path.isSimple());
  var p = path.getCurrentPoint();
  assertEquals(55, p[0]);
  assertRoughlyEquals(77.32, p[1], 0.01);
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
}


function testCreateSimplifiedPath2() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  path.arc(50, 60, 10, 20, 60, 30, false);
  assertFalse(path.isSimple());
  path = goog.graphics.Path.createSimplifiedPath(path);
  assertTrue(path.isSimple());
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
      'M', 55, 77.32,
      'C', 53.48, 79.08, 51.76, 80, 50, 80], path);
}


function testCreateSimplifiedPath3() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  path.arc(50, 60, 10, 20, 60, 30, true);
  path.close();
  path = goog.graphics.Path.createSimplifiedPath(path);
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
      53.48, 79.08, 51.76, 80, 50, 80, 'X'], path);
  var p = path.getCurrentPoint();
  assertRoughlyEquals(58.66, p[0], 0.01);
  assertRoughlyEquals(70, p[1], 0.01);
}


function testArcToAsCurves() {
  var path = new goog.graphics.Path();
  path.moveTo(58.66, 70);
  path.arcToAsCurves(10, 20, 30, 30, false);
  goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
      'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
}


function testCreateTransformedPath() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.lineTo(0, 10, 10, 10, 10, 0);
  path.close();
  var tx = new goog.graphics.AffineTransform(2, 0, 0, 3, 10, 20);
  var path2 = path.createTransformedPath(tx);
  goog.testing.graphics.assertPathEquals(
      ['M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X'], path);
  goog.testing.graphics.assertPathEquals(
      ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
}


function testTransform() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  path.lineTo(0, 10, 10, 10, 10, 0);
  path.close();
  var tx = new goog.graphics.AffineTransform(2, 0, 0, 3, 10, 20);
  var path2 = path.transform(tx);
  assertTrue(path === path2);
  goog.testing.graphics.assertPathEquals(
      ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
}


function testTransformCurrentAndClosePoints() {
  var path = new goog.graphics.Path();
  path.moveTo(0, 0);
  assertObjectEquals([0, 0], path.getCurrentPoint());
  path.transform(new goog.graphics.AffineTransform(1, 0, 0, 1, 10, 20));
  assertObjectEquals([10, 20], path.getCurrentPoint());
  path.lineTo(50, 50);
  path.close();
  assertObjectEquals([10, 20], path.getCurrentPoint());
}


function testTransformNonSimple() {
  var path = new goog.graphics.Path();
  path.arc(50, 60, 10, 20, 30, 30, false);
  assertThrows(function() {
    path.transform(new goog.graphics.AffineTransform(1, 0, 0, 1, 10, 20));
  });
}


function testAppendPath() {
  var path1 = new goog.graphics.Path();
  path1.moveTo(0, 0);
  path1.lineTo(0, 10, 10, 10, 10, 0);
  path1.close();

  var path2 = new goog.graphics.Path();
  path2.arc(50, 60, 10, 20, 30, 30, false);

  assertTrue(path1.isSimple());
  path1.appendPath(path2);
  assertFalse(path1.isSimple());
  goog.testing.graphics.assertPathEquals([
      'M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X',
      'M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32
  ], path1);
}


function testIsEmpty() {
  var path = new goog.graphics.Path();
  assertTrue('Initially path is empty', path.isEmpty());

  path.moveTo(0, 0);
  assertFalse('After command addition, path is not empty', path.isEmpty());

  path.clear();
  assertTrue('After clear, path is empty again', path.isEmpty());
}
