// Kismet
// Copyright (C) 1994, Joseph W. Reiss, All Rights Reserved
// jreiss@magnus.acs.ohio-state.edu
/////////////////////////////////////////////////////////////////////////////
// You are free to modify this code as you wish for your own personal use.
// You may only REDISTRIBUTE the code unaltered, with this copyright notice
// and all documentation intact.
//
// If you make any significant changes to this program, please drop me a
// line and let me know!

#import <stdio.h>
#import <ctype.h>
#import "Controller.h"
#import "Die.h"

extern int scoreThis(id dice[5], int tag);

static char *rollStrs[] = {
    "No Rolls Left",
    "1 Roll Left",
    "2 Rolls Left",
    "3 Rolls Left"
};

@implementation Controller(ApplicationDelegate)
- appDidInit:sender
{
    [kismetWindow makeKeyAndOrderFront:self];
    usedX = [NXImage findImageNamed:"UsedX"];
    dieView[0] = die1;
    dieView[1] = die2;
    dieView[2] = die3;
    dieView[3] = die4;
    dieView[4] = die5;
    [self readHighScores];
    [self newGame:self];
    return self;
}
@end

@implementation Controller(HighScorePanelDelegate)
- windowWillClose:sender
{
    id		cell;

    if ((sender == highScorePanel) &&
	(cell = [highNames selectedCell]) != nil)
      {
	[cell setEditable:NO];
	[cell setSelectable:NO];
	[cell setBackgroundGray:NX_WHITE];
	[NXApp stopModal];
      }
    return self;
}
@end

@implementation Controller

- newGame:sender
{
    id		cell;
    int		i;

    for (i=0; i<5; i++)
	[dieView[i] setValue:i+1];
    for (i=0; i<6; i++)
      {
	cell = [basicSection findCellWithTag:i];
	[cell setIconPosition:NX_TITLEONLY];
	[cell setTitle:""];
	[cell setBordered:YES];
	scores[i] = -1;
      }
    [self updateBasicTotal];
    for (i=6; i<NUMHANDS; i++)
      {
	cell = [kismetSection findCellWithTag:i];
	[cell setIconPosition:NX_TITLEONLY];
	[cell setTitle:""];
	[cell setBordered:YES];
	scores[i] = -1;
      }
    handsLeft = NUMHANDS;
    lastHand = -1;
    [self updateKismetTotal];
    [self newHand];
    return self;
}

- endGame
{
    int		i;

    [self endHand];
    lastHand = -1;			// Can't undo the last hand
    for (i=NUMSCORES-1;
	 i>=0 && basicScore+kismetScore > highScoreNums[i];
	 i--)
	;
    if (i<NUMSCORES-1)			// User got a high score?
	[self newHighScore:i+1];
    return self;
}

- newHand
{
    id		cell;
    int		i;

    for (i=0; i<5; i++)
      {
	[dieView[i] setState:0];
	[dieView[i] setEnabled:NO];
      }
    scoredHand = YES;
    rollsLeft = NUMROLLS;
    for (i=0; i<NUMHANDS; i++)
      {
	if (scores[i] < 0)
	  {
	    cell = [i<6 ? basicSection : kismetSection findCellWithTag:i];
	    [cell setType:NX_MOMENTARYCHANGE];
	  }
      }
    [rollCount setStringValue:rollStrs[rollsLeft]];
    [roller setEnabled:YES];
    return self;
}

- rollDice:sender
{
    id		cell;
    int		i,j;
  
    if (rollsLeft==0 || handsLeft==0)
	return self;

    for (j=0; j<4; j++)
      {
	for (i=0; i<5; i++)
	    if (![dieView[i] state])
		[dieView[i] roll];
	usleep(250);
      }

    if (scoredHand)
      {
	for (i=0; i<5; i++)
	    [dieView[i] setEnabled:YES];
	for (i=0; i<NUMHANDS; i++)
	  {
	    if (scores[i] < 0)
	      {
		cell = [i<6 ? basicSection : kismetSection findCellWithTag:i];
		[cell setType:NX_MOMENTARYPUSH];
	      }
	  }
      }

    scoredHand = NO;
    lastHand = -1;
    rollsLeft--;
    [rollCount setStringValue:rollStrs[rollsLeft]];
    if (rollsLeft == 0)
	[self endHand];
    return self;
}

- scoreHand:sender
{
    int		i,curHand=[[sender selectedCell] tag];
  
    if (scoredHand ||			// Already scored this hand?
	scores[curHand] >= 0)		// Already used this entry?
	return self;			// Don't do it again

    lastHand = curHand;
    lastRolls = rollsLeft;
    for (i=0; i<5; i++)
	lastSel[i] = [dieView[i] state];

    scores[lastHand] = scoreThis(dieView, lastHand);
    if (scores[lastHand] == 0)
	[[[sender selectedCell] setIconPosition:NX_ICONONLY] setImage:usedX];
    else
      {
	char	scoreStr[4];
	
	sprintf(scoreStr,"%d",scores[lastHand]);
	[[[sender selectedCell] setIconPosition:NX_TITLEONLY]
	 setTitle:scoreStr];
      }
    [[[sender selectedCell] setBordered:NO] setType:NX_MOMENTARYCHANGE];
    if ([sender tag])			// Kismet section
	[self updateKismetTotal];
    else
	[self updateBasicTotal];
    if (--handsLeft)			// Haven't filled all the hands
	[self newHand];
    else				// We've done it all
	[self endGame];
    return self;
}

- endHand
{
    int		i;

    for (i=0; i<5; i++)
      {
	[dieView[i] setState:1];
	[dieView[i] setEnabled:NO];
      }
    [roller setEnabled:NO];
    return self;
}


- undo:sender
{
    id		cell;
    int		i;
    
    if (lastHand >= 0)
      {
	cell = [lastHand < 6 ? basicSection : kismetSection
		findCellWithTag:lastHand];
	if (scores[lastHand] >= 0)
	  {
	    [cell setIconPosition:NX_TITLEONLY];
	    [cell setTitle:""];
	    [cell setBordered:YES];
	    [cell setType:NX_MOMENTARYPUSH];
	    scores[lastHand] = -1;

	    for (i=0; i<5; i++)
	      {
		[dieView[i] setState:lastSel[i]];
		[dieView[i] setEnabled:lastRolls>0];
	      }
	    handsLeft++;
	    scoredHand = NO;
	    rollsLeft = lastRolls;
	    [rollCount setStringValue:rollStrs[rollsLeft]];
	    [roller setEnabled:rollsLeft>0];
	  }
	else
	  {
	    scores[lastHand] = scoreThis(dieView, lastHand);
	    if (scores[lastHand] == 0)
		[[cell setIconPosition:NX_ICONONLY] setImage:usedX];
	    else
	      {
		char	scoreStr[4];
	
		sprintf(scoreStr,"%d",scores[lastHand]);
		[[cell setIconPosition:NX_TITLEONLY] setTitle:scoreStr];
	      }
	    [[cell setBordered:NO] setType:NX_MOMENTARYCHANGE];
	    if (--handsLeft)		// Haven't filled all the hands
		[self newHand];
	    else
		[self endGame];
	  }
	if (lastHand < 6)
	    [self updateBasicTotal];
	else
	    [self updateKismetTotal];
      }
    return self;
}

- newHighScore:(int)rank
{
    int		i,j;

    if (highScorePanel == nil)
      {
	if (![NXApp loadNibSection:"HighScores.nib"
	      owner: self
	      withNames: NO])
	    return nil;
      }
    for (i=0; i<NUMSCORES; i++)
      {
	if (i==rank)
	  {
	    [[[highNames  cellAt:i:0]
	      setStringValue:NXUserName()]
	     setBackgroundGray:NX_LTGRAY];
	    [[highNames  cellAt:i:0] setEditable:YES];
	    [highNames selectTextAt:i:0];
	    [[highScores cellAt:i:0] setIntValue:basicScore+kismetScore];
	  }	
	else 
	  {
	    j = i>rank ? i-1 : i;
	    if (highScoreNums[j] > 0)
	      {
		[[highNames  cellAt:i:0] setStringValue:highScoreNames[j]];
		[[highScores cellAt:i:0] setIntValue:highScoreNums[j]];
	      }
	    else
	      {
		[[highNames  cellAt:i:0] setStringValue:""];
		[[highScores cellAt:i:0] setStringValue:""];
	      }	    
	  }
      }
    [NXApp runModalFor:[highScorePanel makeKeyAndOrderFront: nil]];
    [self writeHighScores];
    return self;
}

- newHighName:sender
{
    int		rank,i;
    id		cell;

    cell = [sender selectedCell];
    rank = [cell tag];

    for (i=NUMSCORES-1; i>rank; i--)
      {
	strcpy(highScoreNames[i],highScoreNames[i-1]);
	highScoreNums[i] = highScoreNums[i-1];
      }
    strcpy(highScoreNames[rank], [cell stringValue]);
    highScoreNums[rank] = basicScore+kismetScore;
    [cell setEditable:NO];
    [cell setSelectable:NO];
    [cell setBackgroundGray:NX_WHITE];
    [NXApp stopModal];
    return self;
}

- showInfoPanel:sender
{
    if (infoPanel == nil)
      {
	if (![NXApp loadNibSection:"Info.nib"
	      owner: self
	      withNames: NO])
	    return nil;
      }
    [infoPanel makeKeyAndOrderFront: nil];
    return self;
}

- showRefCardPanel:sender
{
    if (refCardPanel == nil)
      {
	if (![NXApp loadNibSection:"RefCard.nib"
	      owner: self
	      withNames: NO])
	    return nil;
      }
    [refCardPanel makeKeyAndOrderFront: nil];
    return self;
}

- showScoresPanel:sender
{
    int		i;

    if (highScorePanel == nil)
      {
	if (![NXApp loadNibSection:"HighScores.nib"
	      owner: self
	      withNames: NO])
	    return nil;
      }
    for (i=0; i<NUMSCORES; i++)
      {
	if (highScoreNums[i] > 0)
	  {
	    [[highNames  cellAt:i:0] setStringValue:highScoreNames[i]];
	    [[highScores cellAt:i:0] setIntValue:highScoreNums[i]];
	  }
	else
	  {
	    [[highNames  cellAt:i:0] setStringValue:""];
	    [[highScores cellAt:i:0] setStringValue:""];
	  }	    
      }
    [highScorePanel makeKeyAndOrderFront: nil];
    return self;
}

- updateBasicTotal
{
    int		extra=0,i;

    basicScore = 0;
    for (i=0; i<6; i++)
	if (scores[i] >= 0)
	    basicScore += scores[i];

    [basicTotal setIntValue:basicScore];

    extra=0;
    if (basicScore >= 78)
	extra = 75;
    else if (basicScore >= 71)
	extra = 55;
    else if (basicScore >= 63)
	extra = 35;
    [bonus setIntValue:extra];

    basicScore += extra;
    [basicSectionTotal setIntValue:basicScore];
    [basicSectionTotal2 setIntValue:basicScore];

    [self updateGrandTotal];
    return self;
}

- updateGrandTotal
{
    [grandTotal setIntValue:basicScore+kismetScore];
    return self;
}

- updateKismetTotal
{
    int		i;
  
    kismetScore = 0;
    for (i=6; i<NUMHANDS; i++)
	if (scores[i] >= 0)
	    kismetScore += scores[i];

    [kismetSectionTotal setIntValue:kismetScore];
    [self updateGrandTotal];
    return self;
}

- readHighScores
{
    char	path[MAXPATHLEN];
    FILE	*hiFile;
    int		i;

    sprintf(path, "%s/%s", NXHomeDirectory(), HIGHSCOREFILE);
    if ((hiFile = fopen(path, "r")) == NULL)
      {
	for (i=0; i<NUMSCORES; i++)
	  {
	    highScoreNames[i][0] = '\0';
	    highScoreNums[i] = 0;
	  }
      }
    else
      {
	for (i=0; i<NUMSCORES; i++)
	  {
	    fscanf(hiFile, "%d", &highScoreNums[i]);
	    while (isspace(highScoreNames[i][0] = fgetc(hiFile)))
		;
	    fgets(highScoreNames[i]+1, 80, hiFile);
	    highScoreNames[i][strlen(highScoreNames[i])-1]='\0';
	  }
	fclose(hiFile);
      }
    return self;
}    

- writeHighScores
{
    char	path[MAXPATHLEN];
    FILE	*hiFile;
    int		i;

    sprintf(path, "%s/%s", NXHomeDirectory(), HIGHSCOREFILE);
    if ((hiFile = fopen(path, "w")) != NULL)
      {
	for (i=0; i<NUMSCORES; i++)
	  {
	    fprintf(hiFile, "%d %s\n",
	            highScoreNums[i], highScoreNames[i]);
	  }	
	fclose(hiFile);
      }
    return self;
}    

@end
