//
//  CountingOperation.m
//  Operations
//
//  Created by Vandad Nahavandipoor on 10-08-29.
//  Copyright 2010  All rights reserved.
//

#import "CountingOperation.h"

@implementation CountingOperation

NSUInteger    startingCount;
NSUInteger    endingCount;
BOOL          finished;
BOOL          executing;

- (id) init {
  return([self initWithStartingCount:0
                         endingCount:1000]);
}

- (id) initWithStartingCount:(NSUInteger)paramStartingCount
                 endingCount:(NSUInteger)paramEndingCount{
  
  self = [super init];
  
  if (self != nil){

    /* To są wartości przeznaczone dla metody main. */
    startingCount = paramStartingCount;
    endingCount = paramEndingCount;
    
  }
  
  return(self);
  
}

- (void) start {
  
  /* W przypadku przerwania przed rozpoczęciem operacji
   trzeba natychmiast zakończyć działanie i wygenerować
   wymagane powiadomienia mechanizmu KVO. */
  if ([self isCancelled]){
    /* Operacja ZOSTAŁA przerwana. */
      /* Zapewnienie zgodności z KVO. */
    [self willChangeValueForKey:@"isFinished"];
    finished = YES;
    [self didChangeValueForKey:@"isFinished"];
    return;
    
  } else {
    /* Operacja NIE ZOSTAŁA przerwana. */
      /* Zapewnienie zgodności z KVO. */
    [self willChangeValueForKey:@"isExecuting"];
    executing = YES;
    /* Wywołanie metody main wewnątrz metody start. */
    [self didChangeValueForKey:@"isExecuting"];
    [self main];
    
  }
  
}

- (void) main {
  
  @try {    
    /* To pula autorelease. */
    @autoreleasepool {
      /* Zmienna lokalna, która po zakończeniu zadania powinna mieć przypisaną wartość YES. */
      BOOL taskIsFinished = NO;
      
      /* Utworzenie pętli while tylko wtedy, gdy zmienna
         taskIsFinished ma przypisaną wartość YES lub
         operacja została przerwana. */
      while (taskIsFinished == NO &&
             [self isCancelled] == NO){
        
        /* Wykonanie zadania. */
        NSLog(@"Wątek główny = %@", [NSThread mainThread]);
        NSLog(@"Wątek bieżący = %@", [NSThread currentThread]);
        NSUInteger counter = startingCount;
        for (counter = startingCount;
             counter < endingCount;
             counter++){
          NSLog(@"Licznik = %lu", (unsigned long)counter);
        }
        /* To bardzo ważne polecenie. Dzięki niemu możemy zakończyć pętlę
            i nadal stosować się do reguł przerwania operacji. */
        taskIsFinished = YES;
        
      }
      
      /* Zapewnienie zgodności z KVO. Wygenerowanie wymaganych powiadomień KVO. */
      [self willChangeValueForKey:@"isFinished"];
      [self willChangeValueForKey:@"isExecuting"];
      finished = YES;
      executing = NO;
      [self didChangeValueForKey:@"isFinished"];
      [self didChangeValueForKey:@"isExecuting"];
    }
  }
  @catch (NSException * e) {
    NSLog(@"Exception %@", e);
  }
  
}

- (BOOL)  isFinished{
  /* Funkcja po prostu zwraca wartość. */
  return(finished);
}

- (BOOL)  isExecuting{
  /* Funkcja po prostu zwraca wartość. */
  return(executing);
}

@end