/* 
   Copyright (C) 2012, 2013, 2015, 2022 German A. Arias

   This file is part of FísicaLab application

   FísicaLab is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.
 
   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.
 
   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

#import "FLSolverWithCells.h"

@implementation FLSolverWithCells

- (id) init
{
  self = [super init];

  if (self)
    {
      cells = nil;
      chalkboardWidth = 0;
      chalkboardHeight = 0;
    }

  return self;
}

- (void) dealloc
{
  [cells release];
  [super dealloc];
}

// Accessor methods for cells (chalkboard).
- (void) setCells: (NSArray *)anArray
{
  // Retain the array with all the cells at chalkboard.
  ASSIGN(cells, anArray);
}

- (NSArray *) cells
{
  return cells;
}

// Set the width and height of the chalkboard, in cells.
- (void) withChalkboardWidth: (NSUInteger)aWidth height: (NSUInteger)anHeight
{
  chalkboardWidth = aWidth;
  chalkboardHeight = anHeight;
}

// Return the width of chalkboard, in cells.
- (NSUInteger) chalkboardWidth
{
  return chalkboardWidth;
}

// Return the height of chalkboard, in cells.
- (NSUInteger) chalkboardHeight
{
  return chalkboardHeight;
}

- (void) searchAppliedElementsAt: (NSNumber *)identifier
		      andStoreIn: (NSMutableArray *)anArray
{
  [self searchAppliedElementsAt: identifier
		     andStoreIn: anArray
		 withPostionsIn: nil];
}

- (void) searchAppliedElementsAt: (NSNumber *)identifier
		      andStoreIn: (NSMutableArray *)anAppliedArray
		  withPostionsIn: (NSMutableArray *)posAppliedArray
{
  NSUInteger pos = 0, totalCells;
  NSEnumerator *search;
  NSNumber *ident, *aCell;

  NSMutableArray *anArray = [NSMutableArray array];
  NSMutableArray *posArray = nil;

  if (posAppliedArray != nil)
    {
      posArray = [NSMutableArray array];
    }
  
  totalCells = chalkboardWidth*chalkboardHeight - 1;
  
  search = [cells objectEnumerator];

  // Get the position of the element at chalkboard.
  while ((aCell = [search nextObject]))
    {
      if ([aCell intValue] == [identifier intValue])
	{
	  break;
	}
      
      pos += 1;
    }

  if ( (pos%chalkboardWidth != 0) &&
       (pos%chalkboardWidth != (chalkboardWidth - 1)) )
    {
      
      if (pos >= 1)
	{
	  ident = [NSNumber numberWithInt:
			      [[cells objectAtIndex: pos - 1] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"W"];
		}
	    }
	}
      
      if (pos >= (chalkboardWidth - 1))
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - (chalkboardWidth - 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"NE"];
		}
	    }
	}
      
      if (pos >= chalkboardWidth)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"N"];
		}
	    }
	}
      
      if (pos >= (chalkboardWidth + 1))
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - (chalkboardWidth + 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"NW"];
		}
	    }
	}
      
      if (pos + 1 <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
			      [[cells objectAtIndex: pos + 1] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];
	      
	      if (posArray != nil)
		{
		  [posArray addObject: @"E"];
		}
	    }
	}
      
      if (pos + (chalkboardWidth - 1) <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + (chalkboardWidth - 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"SW"];
		}
	    }
	}
      
      if (pos + chalkboardWidth <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"S"];
		}
	    }
	}
      
      if (pos + (chalkboardWidth + 1) <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + (chalkboardWidth + 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"SE"];
		}
	    }
	}
    }
  else if (pos%chalkboardWidth == 0)
    {
      if (pos >= (chalkboardWidth - 1))
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - (chalkboardWidth - 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"NE"];
		}
	    }
	}
      
      if (pos >= chalkboardWidth)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"N"];
		}
	    }
	}
      
      if (pos + 1 <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
			      [[cells objectAtIndex: pos + 1] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"E"];
		}
	    }
	}
      
      if (pos + chalkboardWidth <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"S"];
		}
	    }
	}
      
      if (pos + (chalkboardWidth + 1) <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + (chalkboardWidth + 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"SE"];
		}
	    }
	}
    }
  else
    {
      if (pos >= 1)
	{
	  ident = [NSNumber numberWithInt:
			      [[cells objectAtIndex: pos - 1] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"W"];
		}
	    }
	}
      
      if (pos >= chalkboardWidth)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"N"];
		}
	    }
	}
      
      if (pos >= (chalkboardWidth + 1))
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos - (chalkboardWidth + 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"NW"];
		}
	    }
	}
      
      if (pos + (chalkboardWidth - 1) <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + (chalkboardWidth - 1)] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"SW"];
		}
	    }
	}
      
      if (pos + chalkboardWidth <= totalCells)
	{
	  ident = [NSNumber numberWithInt:
		   [[cells objectAtIndex: pos + chalkboardWidth] intValue]];
	  
	  if ([ident intValue] != 0)
	    {
	      [anArray addObject: ident];

	      if (posArray != nil)
		{
		  [posArray addObject: @"S"];
		}
	    }
	}
    }

  [anAppliedArray addObject: anArray];
  
  if (posAppliedArray != nil)
    {
      [posAppliedArray addObject: posArray];
    }
}

@end
