//
//  BCSeries.m
//  BioCocoa
//
//  Created by Scott Christley on 10/11/06.
//  Copyright (c) 2003-2009 The BioCocoa Project.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//  notice, this list of conditions and the following disclaimer in the
//  documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//  derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import "BCSeries.h"
#import "BCPreferences.h"
#import "BCParseSOFT.h"

// Global list of series
static NSMutableDictionary *series = nil;
static NSMutableDictionary *get_all_series()
{
  if (!series) {
    series = [NSMutableDictionary new];

    NSString *aString = [BCPreferences sharedDataSubdirectory: @"GeneExpression"];
    if (aString) {
      NSArray *anArray = [[NSFileManager defaultManager] directoryContentsAtPath: aString];
      if ([anArray count] > 0) {
        int i;
        //printf("%s\n", [[anArray description] UTF8String]);
        for (i = 0; i < [anArray count]; ++i) {
          NSString *fileName = [anArray objectAtIndex: i];
          NSRange r = [fileName rangeOfString: @"GSE"];
          if (r.location == 0) {
            r = [fileName rangeOfString: @"_"];
            r.length = r.location;
            r.location = 0;
            NSString *anId = [fileName substringWithRange: r];
            //printf("%s\n", [anId UTF8String]);
            BCSeries *aSeries = [[BCSeries alloc] initWithId: anId];
            [aSeries setValue: fileName forKey: @"Data File"];
            [series setObject: aSeries forKey: anId];
          }
        }
      }
    }
  }
  return series;
}

static NSMutableArray *internalKeys = nil;
static NSMutableArray *get_internal_keys()
{
  if (!internalKeys) {
    internalKeys = [NSMutableArray new];
    [internalKeys addObject: @"id"];
    [internalKeys addObject: @"Data File"];
  }
  return internalKeys;
}

@implementation BCSeries

// Access global list of series
+ (NSDictionary *)getAllSeries
{
  return [NSDictionary dictionaryWithDictionary: get_all_series()];
}

+ (BCSeries *)seriesWithId: (NSString *)anId
{
  NSDictionary *d = get_all_series();
  return [d objectForKey: anId];
}

+ (void)addSeries: (BCSeries *)aSeries
{
  NSString *anId = [aSeries getId];
  NSMutableDictionary *d = get_all_series();
  [d setObject: aSeries forKey: anId];
}

+ (NSSet *)keysForSeries: (NSArray *)seriesList withInternalKeys: (BOOL)flag
{
  if (!seriesList) return [NSSet set];
  NSMutableSet *theKeys = [NSMutableSet set];
  NSArray *iKeys;
  if (!flag) iKeys = get_internal_keys();
  int i;
  for (i = 0; i < [seriesList count]; ++i) {
    BCSeries *aSeries = [seriesList objectAtIndex: i];
    NSArray *a = [aSeries allKeys];
    if (!flag) {
      a = [NSMutableArray arrayWithArray: a];
      [(NSMutableArray *)a removeObjectsInArray: iKeys];
    }
    [theKeys addObjectsFromArray: a];
  }

  return [NSSet setWithSet: theKeys];
}

// Default constructor
- initWithId: (NSString *)anId
{
  self = [super init];
  if (self) {
    attributes = [NSMutableDictionary new];
    [attributes setObject: anId forKey: @"id"];
    isLoaded = NO;
  }
  return self;
}

- loadIfNecessary
{
  if (isLoaded) return self;
  NSString *aString = [BCPreferences sharedDataSubdirectory: @"GeneExpression"];
  NSMutableString *fileName = [NSMutableString stringWithString: aString];
  [fileName appendString: @"/"];
  [fileName appendString: [self getId]];
  [fileName appendString: @"_family.soft"];
  BCParseSOFT *parser = [BCParseSOFT new];
  if ([parser parseFile: fileName]) isLoaded = YES;
  [parser release];
  return self;
}

// Accessor methods
- (NSString *)getId
{
  return [attributes objectForKey: @"id"];
}

- (id)valueForKey: (NSString *)aKey
{
  id aValue = [attributes objectForKey: aKey];
  if ((aValue) && ([aValue isKindOfClass: [NSArray class]])) {
    if ([aValue count] == 0) return nil;
    else return [aValue objectAtIndex: 0];
  }
  return aValue;
}

- (NSArray *)valuesForKey: (NSString *)aKey
{
  id aValue = [attributes objectForKey: aKey];
  if (!aValue) return [NSArray array];
  if ([aValue isKindOfClass: [NSArray class]]) {
    return aValue;
  } else
    return [NSArray arrayWithObject: aValue];
}

- (void)setValue:(id)aValue forKey:(NSString *)aKey
{
  id anEntry = [attributes objectForKey: aKey];
  if (!anEntry)
    [attributes setObject: aValue forKey: aKey];
  else {
    if ([anEntry isKindOfClass: [NSArray class]]) {
      [anEntry addObject: aValue];
    } else {
      NSMutableArray *a = [NSMutableArray arrayWithObject: anEntry];
      [a addObject: aValue];
      [attributes setObject: a forKey: aKey];
    }
  }
}

- (NSArray *)allKeys
{
  return [attributes allKeys];
}

- (BOOL)isLoaded
{
  return isLoaded;
}

//
//
//
- (NSString *)seriesDescription
{
  int i;
  NSArray *a;
  NSString *v;
  NSMutableString *s = [NSMutableString string];
  [s appendString: @"Series: "];
  [s appendString: [self getId]];
  [s appendString: @"\n"];
  if (!isLoaded) return s;

  v = [self valueForKey: @"Series_title"];
  if (v) [s appendString: v];

  v = [self valueForKey: @"Series_status"];
  if (v) {
    [s appendString: @"\n\nStatus: "];
    [s appendString: v];
  }
  
  v = [self valueForKey: @"Series_submission_date"];
  if (v) {
    [s appendString: @"\nSubmission: "];
    [s appendString: v];
  }
  
  v = [self valueForKey: @"Series_last_update_date"];
  if (v) {
    [s appendString: @"\nLast Update: "];
    [s appendString: v];
  }
  
  v = [self valueForKey: @"Series_pubmed_id"];
  if (v) {
    [s appendString: @"\nPubmed: http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=PubMed&term="];
    [s appendString: v];
  }
  
  v = [self valueForKey: @"Series_type"];
  if (v) {
    [s appendString: @"\nType: "];
    [s appendString: v];
  }

  [s appendString: @"\n\nSummary:\n"];
  a = [self valuesForKey: @"Series_summary"];
  for (i = 0; i < [a count]; ++i) {
    [s appendString: @"\t"];
    [s appendString: [a objectAtIndex: i]];
    [s appendString: @"\n"];
  }

  v = [self valueForKey: @"Series_overall_design"];
  if (v) {
    [s appendString: @"\nOverall Design:\n"];
    [s appendString: v];
  }

  [s appendString: @"\n\nContact:\n"];
  v = [self valueForKey: @"Series_contact_name"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_email"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_laboratory"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_department"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_institute"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_address"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_city"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_zip/postal_code"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }
  v = [self valueForKey: @"Series_contact_country"];
  if (v) {
    [s appendString: v];
    [s appendString: @"\n"];
  }

  [s appendString: @"\nPlatforms:\n"];
  a = [self valuesForKey: @"Series_platform_id"];
  for (i = 0; i < [a count]; ++i) {
    [s appendString: [a objectAtIndex: i]];
    [s appendString: @"\n"];
  }

  [s appendString: @"\nSamples:\n"];
  a = [self valuesForKey: @"Series_sample_id"];
  for (i = 0; i < [a count]; ++i) {
    [s appendString: [a objectAtIndex: i]];
    [s appendString: @"\n"];
  }

  return s;
}

- (NSString *)seriesHTMLDescription
{
  //int i;
  //NSArray *a;
  NSString *v;
  NSMutableString *s = [NSMutableString string];
  [s appendString: @"<html>\n"];
  [s appendString: @"<body>\n"];
  [s appendString: @"Series: "];
  [s appendString: [self getId]];
  [s appendString: @"<br>"];
  if (!isLoaded) goto done;

  v = [self valueForKey: @"Series_pubmed_id"];
  if (v) {
    [s appendString: @"Pubmed: <a href=\"http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=PubMed&term="];
    [s appendString: v];
    [s appendString: @"\">"];
    [s appendString: v];
    [s appendString: @"</a><br>"];
  }

done:
  [s appendString: @"</body>\n"];
  [s appendString: @"</html>\n"];

  return s;
}

@end
