/*
 * [TestSort.java]
 *
 * Summary: Demonstrate how to sort a Collection in Various orders using Sun's Collections.sort.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2009-01-01
 */
package com.mindprod.example;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import static java.lang.System.*;

/**
 * Demonstrate how to sort a Collection in Various orders using Sun's Collections.sort.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2009-01-01
 * @since 2009-01-01
 */
public class TestSort
    {
    public static void main( String[] args )
        {
        // build ArrayList of Animals
        ArrayList<Animal> animals = new ArrayList<>( 5 );
        animals.add( new Animal( "panther", Color.BLACK, 4 ) );
        animals.add( new Animal( "frog", Color.GREEN, 4 ) );
        animals.add( new Animal( "crab", Color.RED, 10 ) );
        animals.add( new Animal( "elephant", Color.GRAY, 2 ) );
        animals.add( new Animal( "spider", Color.BLACK, 8 ) );
        out.println( "sort in Natural Order (by horns)" );
        Collections.sort( animals );
        for ( Animal animal : animals )
            {
            out.println( animal.toString() );
            }
        out.println( "sort in Reverse Natural Order (by horns)" );
        Collections.sort( animals, Collections.reverseOrder() );
        for ( Animal animal : animals )
            {
            out.println( animal.toString() );
            }
        out.println( "sort alphabetically" );
        Collections.sort( animals, new Animal.Alphabetically() );
        for ( Animal animal : animals )
            {
            out.println( animal.toString() );
            }
        out.println( "sort reverse alphabetically" );
        Collections.sort( animals, Collections.reverseOrder( new Animal.Alphabetically() ) );
        for ( Animal animal : animals )
            {
            out.println( animal.toString() );
            }
        out.println( "sort by color" );
        Collections.sort( animals, new Animal.ByRGB() );
        for ( Animal animal : animals )
            {
            out.println( animal.toString() );
            }
        }
    }

/**
 * objects we will sort, represent animals, not nested
 */
class Animal implements Comparable<Animal>
    {
    /**
     * what color this animal is.
     */
    private final Color color;

    /**
     * name of the animal
     */
    private final String name;

    /**
     * how many legs this animal has
     */
    private final int legs;

    /**
     * constructor
     *
     * @param name  name of the animal.
     * @param color what colour the animal is
     * @param legs  how many legs the animal has
     */
    Animal( String name, Color color, int legs )
        {
        this.name = name;
        this.color = color;
        this.legs = legs;
        }

    /**
     * Sort by elapsedTime, fastest first.
     * Defines default the sort order for Animal Objects.
     * Compare this Animal with another Animal.
     * Compares legs then color.getRGB() & 0xffffff.
     * Informally, returns (this-other) or +ve if this is more positive than other.
     *
     * @param other other Animal to compare with this one
     *
     * @return +ve if this&gt;other, 0 if this==other, -ve if this&lt;other
     */
    public final int compareTo( Animal other )
        {
        int diff = this.legs - other.legs;
        if ( diff != 0 )
            {
            return diff;
            }
        return ( this.color.getRGB() & 0xffffff ) - ( other.color.getRGB() & 0xffffff );
        }

    /**
     * what colour is the animal
     *
     * @return colour
     */
    public Color getColor()
        {
        return color;
        }

    /**
     * how many legs has this animal?
     *
     * @return number of legs
     */
    public int getLegs()
        {
        return legs;
        }

    /**
     * override usual ToString to give a debugging representation.
     *
     * @return name, color, legs as a string.
     */
    public String toString()
        {
        return name + "  " + color + " " + legs;
        }

    /**
     * Describe/summarise the comparison here..
     *
     * @author ...
     * @version 1.0 2009-04-28 - initial release
     * @since 2009-04-28
     */
    static class Alphabetically implements Comparator<Animal>
        {
        /**
         * Describe/summarise the comparison here..
         * Defines an alternate sort order for Animal.
         * Compare two Animal Objects.
         * Compares name.
         * Informally, returns (a-b), or +ve if a is more positive than b.
         *
         * @param a first Animal to compare
         * @param b second Animal to compare
         *
         * @return +ve if a&gt;b, 0 if a==b, -ve if a&lt;b
         */
        public final int compare( Animal a, Animal b )
            {
            return a.name.compareToIgnoreCase( b.name );
            }
        }

    /**
     * Comparator for sorting Animals by Color then legs
     */
    static class ByRGB implements Comparator<Animal>
        {
        /**
         * compare two animal objects
         *
         * @param o1 first object
         * @param o2 second object
         *
         * @return +ve if o1 is bigger, -ve if smaller, 0 if equal
         */
        public int compare( Animal o1, Animal o2 )
            {
            int diff = ( o1.color.getRGB() & 0xffffff ) - ( o2.color.getRGB() & 0xffffff );
            if ( diff != 0 )
                {
                return diff;
                }
            return o1.legs - o2.legs;
            }
        }
    }