/*
 File:       PopupInTable.m

 Contains:   Source code for the Controller of the popup menu button
             used in the "Input" window, see also InputController.m

 Written by: Eric Simenel

 Created:    May 1997

 Copyright:  (c)1997 by Apple Computer, Inc., all rights reserved.

 Change History (most recent first):

 You may incorporate this sample code into your applications without
 restriction, though the sample code has been provided "AS IS" and the
 responsibility for its operation is 100% yours.  However, what you are
 not permitted to do is to redistribute the source as "DSC Sample Code"
 after having made changes. If you're going to re-distribute the source,
 we require that you make it clear in the source that the code was
 descended from Apple Sample Code, but that you've made changes.
*/

#import "PopupInTable.h"
#import "ComicsObj.h"
#import "InputController.h"

@implementation PopupInTable

// private _reset
- (void)_reset
{
    pub = nil;
    pubTitle = pubChoice = -1;
    alreadyRemoved = 0;
}

// private _updateCurrentEditedRowWithPubRemoval
- (void)_updateCurrentEditedRowWithPubRemoval:(BOOL)removal
{
    if (removal)
      {
        // the pop up is removed from the super view, so it disappears
        if (!alreadyRemoved) [pub removeFromSuperview];
        alreadyRemoved = 1;
      }
    // and let's update the current edited line
    [[ic inputView] deselectRow:pubTitle];
    [[ic inputView] selectRow:pubTitle byExtendingSelection:NO];
}

- (id)init
{
    if (self = [super init])
        [self _reset];
    return self;
}

- (void)releasePub
{
    if (pub)
      {
        // first let's make the pop up disappear and update the current edited line
        [self _updateCurrentEditedRowWithPubRemoval:YES];
        // now we can release the pop up itself
        [pub release];
        // and reset our private stuff to prevent confusion later on
        [self _reset];
      }
}

// the user just selected a menu item, let's see what to do
- (void)pubSelect:(id)sender
{
    CTitle *thisTitle = [[ic array] objectAtIndex:pubTitle];
    short mod = 0, choice = [pub indexOfSelectedItem], newFlagT = 0, fl = [thisTitle titleFlags];
    short brands[] = {mskMarvel, mskDC, mskOther};
    short series[] = {mskLong, mskMini};
    short kinds[]  = {mskMain, mskDual};
    short states[] = {mskLive, mskDead};
    short grades[] = {mskMint, mskFine, mskGood, mskPoor, mskMiss};
    short types[]  = {mskComics, mskLuxe, mskNewForm, mskMagazine};
    short cntnts[] = {mskStory, mskInfo, mskReprint};
    short i, j;
    switch (pubChoice)
      {
        // trivial, we modify the title attributes
        case 3: case 4: case 5: case 6:
          {
              switch (pubChoice)
                {
                  case 3: newFlagT = ((fl & mskNotBrand ) | brands[choice]); break;
                  case 4: newFlagT = ((fl & mskNotSeries) | series[choice]); break;
                  case 5: newFlagT = ((fl & mskNotKind  ) | kinds[choice]); break;
                  case 6: newFlagT = ((fl & mskNotState ) | states[choice]); break;
                }
              if (newFlagT != fl)
                {
                  CTitle *newTitle = [[CTitle alloc] initWithAbb:[thisTitle abb] withTitle:[thisTitle title] withFlag:newFlagT];
                  [comicsBase modTitle:thisTitle withNewTitle:newTitle];
                  [[ic array] replaceObjectAtIndex:pubTitle withObject:newTitle];
                  mod = 1;
                }
              break;
          }
        // use charIshMenu and shortIshMenu to determine what to do, and on what
        case 7: case 8: case 9: case 10: case 11: case 12:
          {
              CIssue *thisIssue, *newIssue;
              NSMenuItem *mi;
              char strDate[10];
              switch (charIshMenu[choice])
                {
                  // move the selected issue (curIshArray[pubTitle]) to this edit month (shortIshMenu[choice])
                  case 'm':
#if debug
                      NSLog(@"choice m for date %@", [CComics nsStrDate:shortIshMenu[choice]]);
#endif
                      thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]];
                      if (shortIshMenu[choice] != [thisIssue editMonth])
                        {
                          newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:shortIshMenu[choice] withBuy:[thisIssue buyMonth] withFlag:[thisIssue issueFlags]];
                          [thisTitle modIssue:thisIssue withNewIssue:newIssue];
                          mod = 1;
                          [self _updateCurrentEditedRowWithPubRemoval:YES];
                        }
                      break;
                  // select the (shortIshMenu[choice]) issue and put it in curIshArray[pubTitle]
                  // only useful when many issues of the same title are published the same month (weekly and bi-weekly)
                  // see Action Comics run from 601 to 640 for example
                  case 's':
#if debug
                      NSLog(@"choice s for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]);
#endif
                      for(i=0, j=-1; (j==-1); i++) if (charIshMenu[i] == 'w') j = i;
                      mi = [pub itemAtIndex:j];
                      strcpy(strDate, [[mi title] cString]);
                      strDate[1] = ' ';
                      [mi setTitle:[NSString stringWithCString:strDate]];
                      mi = [pub itemAtIndex:choice];
                      strcpy(strDate, [[mi title] cString]);
                      strDate[1] = '>';
                      [mi setTitle:[NSString stringWithCString:strDate]];
                      charIshMenu[j] = 's';
                      charIshMenu[choice] = 'w';
                      [ic curIshArray][pubTitle] = shortIshMenu[choice];

                      [ic setTheBuyMonth:[[[thisTitle issues] objectAtIndex:[thisTitle findIssue:shortIshMenu[choice]]] buyMonth]];

                      [self _updateCurrentEditedRowWithPubRemoval:YES];
                      [[[[ic inputView] window] contentView] addSubview:pub];
                      alreadyRemoved = 0;
                      break;
                  // nothing to do here, this menuitem is just for the user to know which issue we're working upon.
                  // it is displayed with a starting ">>"
                  case 'w':
#if debug
                      NSLog(@"choice w for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]);
#endif
                      break;
                  // add issue (shortIshMenu[choice])
                  // or move it to this edit month (the current column) if it was already existing
                  case 'a':
#if debug
                      NSLog(@"choice a for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]);
#endif
                      if ((j = ([thisTitle findIssue:shortIshMenu[choice]])) == -1)
                        {
                          newIssue = [[CIssue alloc] initWithIsh:shortIshMenu[choice] withEdit:([ic theEditMonth]-12+pubChoice) withBuy:[ic theBuyMonth] withFlag:defaultFI];
                          [thisTitle addIssue:newIssue];
                          mod = 1;
                          [self _updateCurrentEditedRowWithPubRemoval:YES];
                        }
                      else
                        {
                          short newFlagI;
                          thisIssue = [[thisTitle issues] objectAtIndex:j];
                          newFlagI = ([thisIssue issueFlags] & mskNotGrade) | mskMint;
                          newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:([ic theEditMonth]-12+pubChoice) withBuy:[ic theBuyMonth] withFlag:newFlagI];
                          [thisTitle modIssue:thisIssue withNewIssue:newIssue];
                          mod = 1;
                          [self _updateCurrentEditedRowWithPubRemoval:YES];
                        }
                      break;
                  // delete the issue (shortIshMenu[choice]) except if it is the last one.
                  // I do this to not to have to test against empty issues array in CTitle or CComics methods all the time
                  case 'd':
#if debug
                      NSLog(@"choice d for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]);
#endif
                      if ([thisTitle nbIssues] > 1)
                        {
                          thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]];
                          [thisTitle deleteIssue:thisIssue];
                          mod = 1;
                          [ic curIshArray][pubTitle] = [[[thisTitle issues] lastObject] issueNumber];
                          [self _updateCurrentEditedRowWithPubRemoval:YES];
                        }
                      else NSRunAlertPanel(@"Comics", @"You can't delete the last issue. Delete the title instead.", @"OK", nil, nil);
                      break;
                  // the "Other..." choice, transform the current cell in an editable one, and start the edition
                  // we'll get the user input in setObjectValue:forTableColumn:row: of InputController
                  case 'o':
#if debug
                      NSLog(@"choice o");
#endif
                      [[[[ic inputView] tableColumns] objectAtIndex:pubChoice] setEditable:YES];
                      [self _updateCurrentEditedRowWithPubRemoval:YES];
                      [[ic inputView] editColumn:pubChoice row:pubTitle withEvent:nil select:YES];
                      break;
                  // nothing to do here, "empty" menu item.
                  case ' ':
#if debug
                      NSLog(@"choice nothing");
#endif
                      break;
                }
              break;
          }
        // trivial, we modify the issue (from the "Issue" column) attributes
        case 15: case 16: case 17:
          {
              CIssue *thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]];
              short newFlagI = 0, fli = [thisIssue issueFlags];
              switch (pubChoice)
                {
                  case 15: newFlagI = ((fli & mskNotGrade) | grades[choice]); break;
                  case 16: newFlagI = ((fli & mskNotType ) | types[choice]); break;
                  case 17: newFlagI = ((fli & mskNotCntnt) | cntnts[choice]); break;
                }
              if (newFlagI != fli)
                {
                  CIssue *newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:[thisIssue editMonth] withBuy:[thisIssue buyMonth] withFlag:newFlagI];
                  [thisTitle modIssue:thisIssue withNewIssue:newIssue];
                  mod = 1;
                }
              break;
          }
      }
    // let's not forget to signal that the database has changed
    if (mod) [ic contentChanged];
}

- (void)setUpPopup;
{
    pubTitle = [[ic inputView] clickedRow];
    // has the user clicked in an "empty" row?
    if (pubTitle >= [[ic array] count]) return;
    
    pubChoice = [[ic inputView] clickedColumn];
    if ((pubChoice > 2) && (pubChoice != 13) && (pubChoice != 14))
      {
        CTitle *thisTitle = [[ic array] objectAtIndex:pubTitle];
        CIssue *thisIssue = nil;
        char miTitle[10];
        short i, j, k, k2, nbMI;
        NSRect aRect;

        // get the rectangle of the clicked cell
        aRect = [[ic inputView] frameOfCellAtColumn:pubChoice row:pubTitle];
        // convert it in window coordinates
        aRect = [[[[ic inputView] window] contentView] convertRect:aRect fromView:[ic inputView]];
        // add a little extra width
        aRect.size.width += 28;
        // and create the pop up button there
        pub = [[NSPopUpButton alloc] initWithFrame:aRect pullsDown:NO];
        [pub setFont:((pubChoice >= 7) && (pubChoice <= 12))?[ic fontNonProp]:[ic fontProp]];
        // and set the target and action so that we know when the user is using it
        [pub setTarget:self];
        [pub setAction:@selector(pubSelect:)];
        // and now let's put some menu items in the pop up depending on the clicked column
        if ((pubChoice >= 14) && (pubChoice <= 16))
            thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]];
        switch (pubChoice)
          {
            case 3:
                [pub addItemWithTitle:@"Marvel"];
                [pub addItemWithTitle:@"DC"];
                [pub addItemWithTitle:@"Other"];
                [pub selectItemWithTitle:[thisTitle brand]];
                break;
            case 4:
                [pub addItemWithTitle:@"Long"];
                [pub addItemWithTitle:@"Mini"];
                [pub selectItemWithTitle:[thisTitle series]];
                break;
            case 5:
                [pub addItemWithTitle:@"Main"];
                [pub addItemWithTitle:@"Dual"];
                [pub selectItemWithTitle:[thisTitle kind]];
                break;
            case 6:
                [pub addItemWithTitle:@"Live"];
                [pub addItemWithTitle:@"Dead"];
                [pub selectItemWithTitle:[thisTitle tstate]];
                break;
            case 7: case 8: case 9: case 10: case 11: case 12:
                j = -1;
                i = [ic theEditMonth] - 12 + pubChoice;
                for(k=0; k<5; k++) monthArray[k] = -1;
                nbma = 0; nbMI = 0;
                for(k = [thisTitle nbIssues]-1; (k >= 0) && (j == -1); k--)
                    if (([thisIssue = [[thisTitle issues] objectAtIndex:k] editMonth] == i) && !([thisIssue issueFlags] & mskMiss)) j = k;
                if (j != -1)
                  {
                    [ic setTheBuyMonth:[thisIssue buyMonth]];
                    for(k2=j; (k2>=0) && ([thisIssue = [[thisTitle issues] objectAtIndex:k2] editMonth] == i); k2--)
                        if (!([thisIssue issueFlags] & mskMiss)) monthArray[nbma++] = [thisIssue issueNumber];
                  }
                if (nbma == 0)
                  {
                    short lastIshP1 = [[[thisTitle issues] lastObject] issueNumber] + 1;
                    [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, "  "),gnums[lastIshP1])]];
                    charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = lastIshP1;
                    [pub addItemWithTitle:@""]; charIshMenu[nbMI++] = ' ';
                    for(k=lastIshP1-2; k<lastIshP1; k++) if (k >= 0)
                      {
                        [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, "  "),gnums[k])]];
                        charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k;
                      }
                    for(k=lastIshP1+1; k<lastIshP1+6; k++)
                      {
                        [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, "  "),gnums[k])]];
                        charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k;
                      }
                    [pub addItemWithTitle:@"   "]; charIshMenu[nbMI++] = ' ';
                    [pub addItemWithTitle:@"Other..."];
                    charIshMenu[nbMI] = 'o'; shortIshMenu[nbMI++] = 0;
                  }
                else
                  {
                    for(k=1; k <= 6; k++)
                      {
                        strcat(strcpy(miTitle, " "), [CComics cStrDate:[ic theEditMonth]-6+k]);
                        [pub addItemWithTitle:[NSString stringWithCString:miTitle]];
                        charIshMenu[nbMI] = 'm'; shortIshMenu[nbMI++] = [ic theEditMonth]-6+k;
                      }
                    [pub addItemWithTitle:@" "]; charIshMenu[nbMI++] = ' ';
                    for(k=nbma-1; k>=0; k--)
                      {
                        strcpy(miTitle, "  ");
                        strcat(miTitle, gnums[monthArray[k]]);
                        miTitle[0] = '>';
                        if (k == 0) miTitle[1] = '>';
                        [pub addItemWithTitle:[NSString stringWithCString:miTitle]];
                        charIshMenu[nbMI] = (k==0)?'w':'s'; shortIshMenu[nbMI++] = monthArray[k];
                      }
                    [pub addItemWithTitle:@""]; charIshMenu[nbMI++] = ' ';
                    for(k=monthArray[nbma-1]-2; k<monthArray[nbma-1]; k++) if (k >= 0)
                      {
                        [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, "  "),gnums[k])]];
                        charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k;
                      }
                    for(k=monthArray[0]+1; k<monthArray[0]+6; k++)
                      {
                        [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, "  "),gnums[k])]];
                        charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k;
                      }
                    [pub addItemWithTitle:@"  "]; charIshMenu[nbMI++] = ' ';
                    [pub addItemWithTitle:@"Delete"];
                    [ic curIshArray][pubTitle] = monthArray[0];
                    charIshMenu[nbMI] = 'd'; shortIshMenu[nbMI++] = [ic curIshArray][pubTitle];
                    [self _updateCurrentEditedRowWithPubRemoval:NO];
                    [pub addItemWithTitle:@"   "]; charIshMenu[nbMI++] = ' ';
                    [pub addItemWithTitle:@"Other..."];
                    charIshMenu[nbMI] = 'o'; shortIshMenu[nbMI++] = 0;
                  }
                break;
            case 15:
                [pub addItemWithTitle:@"Mint"];
                [pub addItemWithTitle:@"Fine"];
                [pub addItemWithTitle:@"Good"];
                [pub addItemWithTitle:@"Poor"];
                [pub addItemWithTitle:@"Missing"];
                [pub selectItemWithTitle:[thisIssue grade]];
                break;
            case 16:
                [pub addItemWithTitle:@"Comics"];
                [pub addItemWithTitle:@"Luxe"];
                [pub addItemWithTitle:@"New Format"];
                [pub addItemWithTitle:@"Magazine"];
                [pub selectItemWithTitle:[thisIssue ishtype]];
                break;
            case 17:
                [pub addItemWithTitle:@"Story"];
                [pub addItemWithTitle:@"Info"];
                [pub addItemWithTitle:@"Reprint"];
                [pub selectItemWithTitle:[thisIssue content]];
                break;
          }
        // finally add the pop up button to the content view of the window
        [[[[ic inputView] window] contentView] addSubview:pub];
        // and remember it's here
        alreadyRemoved = 0;
      }
}

@end
