
// Default container for all palettes
ArrayList ColorSet;

// Predefined Palettes

void InitPalettes()
{
  /*new Palette(  new color[]{color(230,  0,  0), color(221,  0,  23), color(210,  23,  0)},
                new color[]{color(160,  0,  0), color(154,  0,  34), color(210,  70,  0)},
                new color[]{color( 80,  0,  0), color( 65,  0,  40), color( 70,  42,  0)} );
                
  new Palette(  new color[]{color( 54,  5,155), color( 42,  0, 234), color(  0,  23,196)},
                new color[]{color( 35, 35,137), color( 54,  0, 134), color(  7,   0,200)},
                new color[]{color( 10, 34, 80), color( 65,  0,  50), color( 30,  42, 60)} );
  */
  new Palette( loadImage( "palette_midwarm.png" ) );
  new Palette( loadImage( "palette_psychogreen.png" ) );
  new Palette( loadImage( "palette_redgreen.png" ) );
  new Palette( loadImage( "palette_seaturtle.png" ) );
}

void LoadPalette(String path)
{
  Palette pal = new Palette( loadImage( path ) );
  if ( REVERSECOLOR )
  {
    pal.Invert();
  }
}

class Palette
{
  // Semi-static subclass.  All versions are held in ColorSets member variable.
  
  color[] High;
  color[] Mid;
  color[] Low;
  
  Palette( color[] High, color[] Mid, color[] Low)
  {
    Register();
    this.High = High;
    this.Mid  = Mid;
    this.Low  = Low;
  }
  
  Palette( PImage img )
  {
    Register();
    
    img.loadPixels();
    int numPixels = img.width * img.height;
    color[] colors = new color[numPixels];
    
    for( int i = 0;i < numPixels; ++i )
    {
      colors[i] = color(img.pixels[i]);
    }
    colors = sort( colors );
    
    int firstThird = numPixels /3;
    int secondThird = firstThird * 2;
    
    Low = new color[firstThird];
    Mid = new color[secondThird - firstThird];
    High = new color[ numPixels - secondThird ];
    
    for( int i = 0; i < firstThird; i++ )
    {
      Low[i] = colors[i];
    }
    
    for( int i = firstThird; i < secondThird; ++i )
    {
      Mid[i - firstThird] = colors[i];
    }
    
    for( int i = secondThird; i < numPixels; ++i )
    {
      High[i - secondThird] = colors[i];
    }
  }
  
  void Register()
  {
    if ( ColorSet == null )
    {
      ColorSet = new ArrayList();
    }
    ColorSet.add( this );
  }
  
  color GetHigh()
  {
    int range = (int)random(High.length);
    return High[range];
  }
  
  color GetMid()
  {
    int range = (int)random(Mid.length);
    return Mid[range];
  }
  
  color GetLow()
  {
    int range = (int)random(Low.length);
    return Low[range];
  }
  
  color GetRand()
  {
    int range = (int)random(3);
    
    switch( range )
    {
      case 0:
        return GetHigh();
      case 1:
        return GetMid();
      case 2:
        return GetLow();
    }
    return color( 255, 255, 255);
  }
  
  void Invert()
  {
    for( int i = 0; i < High.length; ++i )
    {
      High[i] = color( 255 ) - High[i];
    }
    for( int i = 0; i < Mid.length; ++i )
    {
      Mid[i] = color( 255 ) - Mid[i];
    }
    for( int i = 0; i < Low.length; ++i )
    {
      Low[i] = color( 255 ) - Low[i];
    }
  }
  
  void Reverse()
  {
    color[] temp = High;
    High = Low;
    Low = High;
  }
}


