// NewsarticlesMatrix.m


#import "ArticlesMatrix.h"

@implementation ArticlesMatrix

+ newFrame:(const NXRect *)frameRect
{
  self = [super newFrame:frameRect];

  numBitmaps = ARTICLE_NUM_BITMAPS;
  [protoCell setNumBitmaps:numBitmaps];

  numColumns = ARTICLE_NUM_COLUMNS;
  [protoCell setNumColumns:numColumns];
  
  tabs[0] = ARTICLE_TAB_0;
  tabs[1] = ARTICLE_TAB_1;
  [self calcTabs];

  return self;
}

- setupNNTP:(FILE *)newnntpFile
{
  nntpFile = newnntpFile;
}

- fakeReadGroup
{
  Article	*article;
  seenStruct	*seenData;
  long		numSeenStruct = [selectedNewsgroup->seenStorage count];
  long		firstAvailable, lastAvailable,
  		firstUnseen, lastUnseen, number;
  int		i;
  
  firstAvailable = selectedNewsgroup->available.first;
  lastAvailable = selectedNewsgroup->available.last;
  for (number = firstAvailable; (number<=lastAvailable) && (lastAvailable>0);
  				number++) {
    article = [Article newNumber:number];
    [itemsList addObject:article];
  }
  
  seenData = (seenStruct *)(selectedNewsgroup->seenStorage->dataPtr);
  
  for (i=-1; i<numSeenStruct; i++) {
    if (i > -1)
      firstUnseen = seenData[i].last+1;
    else
      firstUnseen = firstAvailable;
      
    if (i < numSeenStruct-1)
      lastUnseen = seenData[i+1].first-1;
    else
      lastUnseen = lastAvailable;
    
    if ((firstUnseen <= lastAvailable) && (lastUnseen >= firstAvailable))
      for (number = MAX(firstUnseen, firstAvailable);
      		number <= MIN(lastUnseen, lastAvailable); number++)
        [[itemsList objectAt:number-firstAvailable] setSeen:FALSE];
  }
  
  [self updateCells];
  [[self superview] display];
  return self;
}



// this makes sure the articles' subjects have been read in before it
// actually draws.
- drawSelf:(const NXRect *)rects :(int)rectCount
{
  int		row, col;
  NXPoint	point = rects[0].origin;
  int		cellIndex, cellFirst, cellLast;
  IconColumnCell *aCell;
  
  if ([self getRow:&row andCol:&col forPoint:&point] != nil) {
    cellFirst = row;
    point.y += rects[0].size.height;
    cellLast = numRows-1;
    if ([self getRow:&row andCol:&col forPoint:&point] != nil)
      cellLast = MIN(cellLast, row);
  
    for (cellIndex=cellFirst; cellIndex<=cellLast; cellIndex++) {
      while (([(aCell = ((IconColumnCell *)(((List *)cellList)
		->dataPtr[cellIndex]))) data][1][0] == '\0')
		&& (cellIndex < numRows)) {
	[self readNNTPFromArticle:(Article *)(aCell->aux)];
      }
    }
  }

  return [super drawSelf:rects :rectCount];
}


- readNNTPFromArticle:(Article *)article
{
  int		inCode;
  char		inCodeText[BUFFER_SIZE];
  int		ch;
  char		subject[BUFFER_SIZE];
  long		number, last;
  int		articleIndex = [itemsList indexOf:article];
  int		row, col;
  
  last = MIN(article->number+ARTICLE_CHUNK, selectedNewsgroup->available.last);
  fprintf(nntpFile, "xhdr subject %ld-%ld\r\n", article->number, last);
  fflush(nntpFile);
  fseek(nntpFile, (long)0, SEEK_END);

  fscanf(nntpFile, "%d %[^\r]\r\n", &inCode, &inCodeText);

  if (inCode != OK_HEAD)
    printf("No way, fix me HEAD.\n"); // fix

  while ((ch = getc(nntpFile)) != '.') {
    ungetc(ch, nntpFile);
    fscanf(nntpFile, "%d %[^\r]\r\n", &number, &subject);

    while ((article != nil) && (number > article->number)) {
      article->bogus = TRUE;
      if (!article->seen)
        [self cellToggleSeen:article->cell];
      article = [itemsList objectAt:++articleIndex];
    }
    if (article != nil) {
      strcpy(article->subject, subject);
      article = [itemsList objectAt:++articleIndex];
    }
  }
  while ((article != nil) && (last > article->number)) {
    article->bogus = TRUE;
    if (!article->seen)
      [self cellToggleSeen:article->cell];
    article = [itemsList objectAt:++articleIndex];
  }
  fgetc(nntpFile);	// \r
  fgetc(nntpFile);	// \n
  fseek(nntpFile, (long)0, SEEK_END);
  
  [self updateCells];
  return self;
}


- (BOOL)itemVisible:item
{
  Article	*article = item;
  BOOL		highlighted = FALSE;
  
  if (article->cell)
    highlighted = [article->cell isHighlighted];
  
  return (article->shown = ((showSeenArticles || !article->seen)
  				|| highlighted)
				&& !article->bogus);
}


- updateCellVisible:(IconColumnCell *)aCell
{
  Article	*article = (Article *)aCell->aux;
  int		row, col;
  BOOL		newShown = [self itemVisible:article];
  
  if (!newShown) {
    if ([self getRow:&row andCol:&col ofCell:article->cell] != nil) {
      [self removeRowAt:row andFree:TRUE];
      [self sizeToCells];
    }
  }

  return self;
}



- cellToggleSeen:(IconColumnCell *)articleCell
{
  Article	*article;

  if (articleCell) {
    article = (Article *)(articleCell->aux);
    
    [article setSeen:!(article->seen)];
    if (article->seen) {
      [selectedNewsgroup addSeenFirst:article->number last: article->number];
    } else {
      [selectedNewsgroup removeSeenFirst:article->number
      			 last: article->number];
    }
  
    [newsgroupsMatrix drawCell:[newsgroupsMatrix selectedCell]];
  }
  return self;
}

#ifdef stupid
- sendAction:(SEL)theAction to:theTarget
{
  id		ret;
  
  ret = [super sendAction:theAction to:theTarget];

  if (realSelectedCell) {

    // mark the current article as read
    [self seenArticleCell:realSelectedCell];
    [self drawCell:realSelectedCell];

    // this is convoluted in order to fill in gaps if available
    // articles are non-contiguous
    cellIndex = [cellList indexOf:realSelectedCell];
    if (cellIndex == 0) {
      [selectedNewsgroup
    		addSeenFirst: 1
		last: ((Article *)realSelectedCell->aux)->number];
    } else {
      [selectedNewsgroup
    		addSeenFirst: (((Article *)
				((IconColumnCell *)
				 [cellList objectAt:(cellIndex-1)])
				->aux))->number+1
		last: ((Article *)realSelectedCell->aux)->number];
    }
  }

  return ret;
}
#endif

- toggleSeen:sender
{
  [self sendAction:@selector(cellToggleSeen:) to:self forAllCells:FALSE];
  [[self superview] display];
}

- showSeenArticles:sender
{
  showSeenArticles = (BOOL)[sender intValue];
  [self updateCells];
  [self sendAction];
  [[self superview] display];
}

- selectWayUp:sender
{
  if (newsgroupsMatrix)
    [newsgroupsMatrix selectUp:sender];
  return self;
}

- selectWayDown:sender;
{
  if (newsgroupsMatrix)
    [newsgroupsMatrix selectDown:sender];
  return self;
}


- setNewsgroup:sender
{
  Newsgroup	*newSelectedNewsgroup = [[sender selectedCell] aux];

  newsgroupsMatrix = sender;
  
  if (newSelectedNewsgroup != selectedNewsgroup) {
    selectedNewsgroup = newSelectedNewsgroup;
    
    [self empty];

    if (selectedNewsgroup != nil) {
      if ([selectedNewsgroup selectOnNNTP:nntpFile]) {
        [self fakeReadGroup];
        [self selectCellAt:-1 :-1];
      } else
        [newsgroupsMatrix updateCells];

      [[newsgroupsMatrix superview] display];
    }
  }
  
  return self;
}


@end
