/*
 * 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.phoenix.schema;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import org.apache.hadoop.hbase.CompareOperator;
import org.apache.phoenix.schema.types.PBoolean;
import org.apache.phoenix.schema.types.PDataType;
import org.junit.Test;

/**
 * @since 3.0
 */
public class SortOrderTest {
	
	@Test
	public void ascSortOrderDoesNotTransformOp() {
	    for (CompareOperator op : CompareOperator.values()) {
	    	assertSame(op, SortOrder.ASC.transform(op));
	    }
	}
	
	@Test
	public void booleanLogic() {
	    assertTrue(PBoolean.INSTANCE.toObject(PDataType.TRUE_BYTES, SortOrder.ASC) == PBoolean.INSTANCE.toObject(
          PDataType.FALSE_BYTES, SortOrder.DESC));
        assertTrue(
            PBoolean.INSTANCE.toObject(PBoolean.INSTANCE.toBytes(true), SortOrder.ASC) == PBoolean.INSTANCE.toObject(
                PBoolean.INSTANCE.toBytes(false), SortOrder.DESC));
        assertTrue(
            PBoolean.INSTANCE.toObject(PBoolean.INSTANCE.toBytes(true,SortOrder.ASC)) == PBoolean.INSTANCE.toObject(
                PBoolean.INSTANCE.toBytes(false,SortOrder.DESC)));

        assertFalse(PBoolean.INSTANCE.toObject(PDataType.FALSE_BYTES, SortOrder.ASC) == PBoolean.INSTANCE.toObject(PDataType.FALSE_BYTES, SortOrder.DESC));
        assertFalse(
            PBoolean.INSTANCE.toObject(PBoolean.INSTANCE.toBytes(false), SortOrder.ASC) == PBoolean.INSTANCE.toObject(
                PBoolean.INSTANCE.toBytes(false), SortOrder.DESC));
        assertFalse(
            PBoolean.INSTANCE.toObject(PBoolean.INSTANCE.toBytes(false,SortOrder.ASC)) == PBoolean.INSTANCE.toObject(
                PBoolean.INSTANCE.toBytes(false,SortOrder.DESC)));
	}

	@Test
	public void descSortOrderTransformsOp() {
	    for (CompareOperator op : CompareOperator.values()) {
			CompareOperator oppositeOp = SortOrder.DESC.transform(op);
	    	switch (op) {
			case EQUAL:
				assertSame(CompareOperator.EQUAL, oppositeOp);
				break;
			case GREATER:
				assertSame(CompareOperator.LESS, oppositeOp);
				break;
			case GREATER_OR_EQUAL:
				assertSame(CompareOperator.LESS_OR_EQUAL, oppositeOp);
				break;
			case LESS:
				assertSame(CompareOperator.GREATER, oppositeOp);
				break;
			case LESS_OR_EQUAL:
				assertSame(CompareOperator.GREATER_OR_EQUAL, oppositeOp);
				break;
			case NOT_EQUAL:
				assertSame(CompareOperator.NOT_EQUAL, oppositeOp);
				break;
			case NO_OP:
				assertSame(CompareOperator.NO_OP, oppositeOp);
				break;
	    	}
	    }		
	}
	
	@Test
    public void defaultIsAsc() {
		assertSame(SortOrder.ASC, SortOrder.getDefault());
	}
	
	@Test
	public void ddlValue() {
		assertSame(SortOrder.ASC, SortOrder.fromDDLValue("ASC"));
		assertSame(SortOrder.ASC, SortOrder.fromDDLValue("asc"));
		assertSame(SortOrder.ASC, SortOrder.fromDDLValue("aSc"));
		assertSame(SortOrder.DESC, SortOrder.fromDDLValue("DESC"));
		assertSame(SortOrder.DESC, SortOrder.fromDDLValue("desc"));
		assertSame(SortOrder.DESC, SortOrder.fromDDLValue("DesC"));		
		
		try {
			SortOrder.fromDDLValue("foo");
		} catch (IllegalArgumentException expected) {
			
		}
	}
	
	@Test
	public void systemValue() {
		assertSame(SortOrder.ASC, SortOrder.fromSystemValue(SortOrder.ASC.getSystemValue()));
		assertSame(SortOrder.DESC, SortOrder.fromSystemValue(SortOrder.DESC.getSystemValue()));		
		assertSame(SortOrder.ASC, SortOrder.fromSystemValue(0));
	}
	
	@Test
	public void invertByte() {
		byte b = 42;
		assertNotEquals(b, SortOrder.invert(b));
		assertEquals(b, SortOrder.invert(SortOrder.invert(b)));
	}
	
	@Test
	public void invertByteArray() {
		byte[] b = new byte[]{1, 2, 3, 4};
		assertArrayEquals(b, SortOrder.invert(SortOrder.invert(b, 0, b.length), 0, b.length));
	}
}
