#import "TuneViewController.h"
#import "EditABCController.h"
#import "Tune.h"
#import "TunePlayer.h"
#import "TuneParser.h"
#import "TuneSettingsController.h"
#import "AppDelegate.h"
#if __IPHONE_3_2
#import "MainViewController.h"
#import "PlaylistViewController.h"
#import "SearchViewController.h"
#import "ManageTunesController.h"
#import "SettingsController.h"
#endif

#define PAGING 1 // Temporary while experimenting
#if PAGING
#import <QuartzCore/QuartzCore.h>
#endif

static TunePlayer *tunePlayer;

@implementation TuneViewController

@synthesize tune;
@synthesize playlist;
@synthesize savedDots;

// Sizes for A4 paper
#define PaperWidth 592
#define PaperHeight 842

#if PAGING

static UILabel *pageLabel;
// Temporary while experimenting
enum {
  ScrollViewModeNotInitialized,
  ScrollViewModePaging,
  ScrollViewModeZooming
};
static int scrollViewMode;
static int currentPage;
static TuneView *tuneView2;
static int page2;
static Tune *tune2;
static CGFloat pendingOffsetDelta;
#define tuneView1 tuneView

- (NSInteger)pageCount
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
	return playlist ? [[playlist loadTunes] count] : [appDelegate.tunes count];
}

- (NSArray *)tunes
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
	return playlist ? [playlist loadTunes] : appDelegate.tunes;
}

- (void)scrollToPage:(NSInteger)page
{
  CGRect frame = scrollView.frame;
  frame.origin.x = frame.size.width * page;
  frame.origin.y = 0;
  [scrollView scrollRectToVisible:frame animated:YES];
//  currentPage = page;
}

- (void)applyNewIndex:(NSInteger)newIndex view:(TuneView *)view
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
	NSInteger pageCount = playlist ? [[playlist loadTunes] count] : [appDelegate.tunes count];
	BOOL outOfBounds = newIndex >= pageCount || newIndex < 0;
printf("applyNewIndex %d %s\n", newIndex, view == tuneView ? "tuneView" : "otherView");

	if ( !outOfBounds ) {
		CGRect pageFrame = tuneView.frame;
		pageFrame.origin.y = 0;
		pageFrame.origin.x = scrollView.frame.size.width * newIndex;
		view.frame = pageFrame;
	} else {
		CGRect pageFrame = tuneView.frame;
		pageFrame.origin.y = scrollView.frame.size.height;
		view.frame = pageFrame;
	}

  if ( view == tuneView1 )
    currentPage = newIndex;
  else
    page2 = newIndex;
  currentPage = newIndex;

	if ( !outOfBounds ) {
    NSArray *tunes = [self tunes];
    if ( currentPage >= 0 && currentPage < [tunes count] ) {
      Tune *t = [tunes objectAtIndex:currentPage];
      [t hydrate];
      view.tune = [t dots];
      if ( view == tuneView )
        tune = t;
      else
        tune2 = t;
    } else
      view.tune = nil;
    [view setNeedsDisplay];
  }
}

- (CGSize)pageSize {
	CGSize pageSize = scrollView.frame.size;
	if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
		return CGSizeMake(pageSize.height, pageSize.width);
	else
		return pageSize;
}

- (void)setPagingMode {
	if ( scrollViewMode != ScrollViewModePaging ) {
    NSLog(@"setPagingMode");
    CGSize pageSize = [self pageSize];
    if ( [tuneView2 superview] == nil )
      [scrollView addSubview:tuneView2];
    CGRect frame = tuneView.frame;
    frame.origin.x += frame.size.width;
    tuneView2.frame = frame;
    
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSInteger pageCount = playlist ? [[playlist loadTunes] count] : [appDelegate.tunes count];
printf("setPaging: count=%d\n", pageCount);

    scrollView.pagingEnabled = YES;
    scrollView.showsVerticalScrollIndicator = scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.contentSize = CGSizeMake(pageSize.width * pageCount, pageSize.height);
    scrollView.contentOffset = CGPointMake(pageSize.width * currentPage, 0);
    
    scrollViewMode = ScrollViewModePaging;
    pageLabel.text = [NSString stringWithFormat:@"Page %d of %d - %@ - %@", currentPage, [self pageCount], playlist.name, tune.title];
[self scrollToPage:currentPage];
  }
}

- (void)setZoomingMode {
	if ( scrollViewMode != ScrollViewModeZooming ) {
    NSLog(@"setZoomingMode");
    scrollViewMode = ScrollViewModeZooming; // has to be set early, or else currentPage will be mistakenly reset by scrollViewDidScroll
    
    [tuneView2 removeFromSuperview];
    
    scrollView.pagingEnabled = NO;
    scrollView.showsVerticalScrollIndicator = scrollView.showsHorizontalScrollIndicator = YES;
    pendingOffsetDelta = scrollView.contentOffset.x;
    scrollView.bouncesZoom = YES;
  }
}

//- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)newScrollView
//{
//  CGFloat pageWidth = scrollView.frame.size.width;
//  float fractionalPage = scrollView.contentOffset.x / pageWidth;
//	NSInteger nearestNumber = lround(fractionalPage);
//
//  if ( nearestNumber < 0 )
//    nearestNumber = 0;
//	if ( currentPage != nearestNumber ) {
//		TuneView *t = tuneView1;
//    tuneView1 = tuneView2;
//    tuneView2 = t;
//		int p = currentPage;
//    currentPage = page2;
//    page2 = p;
//		Tune *s = tune;
//    tune = tune2;
//    tune2 = s;
//	}
//  pageLabel.text = [NSString stringWithFormat:@"Page %d of %d\n%@\n%@", currentPage, [self pageCount], playlist.name, tune.title];
//printf("page %d\n", currentPage);
//}
//
//- (void)scrollViewDidEndDecelerating:(UIScrollView *)newScrollView
//{
//	[self scrollViewDidEndScrollingAnimation:newScrollView];
//}


- (void)viewDidUnload {
//	[pageViews release]; // need to release all page views here; our array is created in loadView, so just releasing it
//	pageViews = nil;
}

//- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
//	if (scrollViewMode == ScrollViewModePaging) {
//    CGFloat pageWidth = scrollView.frame.size.width;
//    float fractionalPage = scrollView.contentOffset.x / pageWidth;
//
//    NSInteger lowerNumber = floor(fractionalPage);
//    NSInteger upperNumber = lowerNumber + 1;
//    
//    if (lowerNumber == currentPage)
//    {
//      if (upperNumber != page2)
//      {
//        [self applyNewIndex:upperNumber view:tuneView1];
//      }
//    }
//    else if (upperNumber == currentPage)
//    {
//      if (lowerNumber != page2)
//      {
//        [self applyNewIndex:lowerNumber view:tuneView2];
//      }
//    }
//    else
//    {
//      if (lowerNumber == page2)
//      {
//        [self applyNewIndex:upperNumber view:tuneView1];
//      }
//      else if (upperNumber == page2)
//      {
//        [self applyNewIndex:lowerNumber view:tuneView1];
//      }
//      else
//      {
//        [self applyNewIndex:lowerNumber view:tuneView1];
//        [self applyNewIndex:upperNumber view:tuneView2];
//      }
//    }
//
//  }
//}
#endif

-(id<TuneViewDelegate>)tuneViewDelegate
{
	return tuneView.delegate;
}

-(void)setTuneViewDelegate:(id<TuneViewDelegate>)delegate
{
	tuneView.delegate = [delegate retain];
}

-(id)initWithTune:(Tune *)aTune
{
	self = [super initWithNibName:@"TuneView" bundle:nil];
	if ( self != nil ) {
    self.tune = aTune;
		self.title = aTune.title;
    saveChangesSheet = NULL;
    multipleTunesSheet = NULL;
    editController = NULL;
    showingABC = NO;
    settingsController = nil;
    showingSettings = NO;
    tunePlayer = nil;
    numPages = 1;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewTapped:) name:@"tap" object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDoubleTapped:) name:@"doubleTap" object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(finishedPlaying:) name:@"finishedPlaying" object:nil]; 
	}
	return self;
}

-(void)viewDidLoad {
  barsHidden = false;
  CGRect bounds;
#if 1//Measuring
  numPages = 1;
  if ( tune ) {
    UIGraphicsBeginImageContext( CGSizeMake( 8, 8 ) );
    numPages = [TuneView drawTune:tune.dots intoContext:UIGraphicsGetCurrentContext() bounds:CGRectMake(0, 0, 8, 8) scale:1.0f];
    if ( numPages < 1 )
      numPages = 1;
    bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, numPages * PaperHeight * kTuneScale );
    UIGraphicsEndImageContext();
  } else
    bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, PaperHeight * kTuneScale );
#else
  bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, PaperHeight * kTuneScale );
#endif
	scrollView = [[UIScrollView alloc] initWithFrame:[mainView bounds]];
	[scrollView setContentSize:bounds.size];
	[scrollView setScrollEnabled:YES];
  scrollView.minimumZoomScale = 0.5f;
  scrollView.maximumZoomScale = 6.0f;
  scrollView.delegate = self;
	scrollView.autoresizesSubviews = YES;
  scrollView.clipsToBounds = YES;
	scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  [scrollView retain];

  tuneView = [[TuneView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 1.0)];
  tuneView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  tuneView.scale = 1.0f;

	tuneView.frame = bounds;
  tuneView.tune = tune ? [tune dots] : nil;
  tuneView.contentMode = UIViewContentModeRedraw;

	[scrollView addSubview:tuneView];
	[mainView addSubview:scrollView];
	[mainView sendSubviewToBack:scrollView];

  scrollView.contentOffset = CGPointMake(40.0f, 50.0f);
  scrollView.contentInset = UIEdgeInsetsMake( 0, 0, 88, 0 );

	[scrollView release];

  self.navigationItem.rightBarButtonItem = self.editButtonItem;

  // Set up the arrays of toolbar items we'll need
  NSArray *items = toolbar.items;
  playItems = [NSMutableArray arrayWithArray:items];
  [playItems removeObject:playButton];
  [playItems retain];
  stopItems = [NSMutableArray arrayWithArray:items];
  [stopItems removeObject:pauseButton];
  [stopItems retain];
  toolbar.items = stopItems;

  abcButton = [[[UIBarButtonItem alloc]
    initWithTitle:@"ABC"
    style:UIBarButtonItemStylePlain 
    target:self 
    action:@selector(editABC)] autorelease];
  [abcButton retain];

#if __IPHONE_3_2
  emailButton.enabled = NO;
  editButton.enabled = NO;
  playButton.enabled = NO;
  [self scrollViewDidEndZooming:scrollView withView:self.view atScale:1.4f];
#endif
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerFinished:) name:@"playerFinished" object:nil];
#if PAGING
  pageLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 500.0, 400.0, 60.0)];
  pageLabel.backgroundColor = [UIColor blackColor];
  pageLabel.textColor = [UIColor whiteColor];
  pageLabel.layer.cornerRadius = 10;
  pageLabel.text = @"Hello";
  pageLabel.alpha = 0.8f;
  pageLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
  [mainView addSubview:pageLabel];

  TuneView *newView = [[TuneView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 1.0)];
  newView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  newView.scale = 1.0f;

	newView.frame = tuneView.frame;
  newView.tune = nil;
  newView.contentMode = UIViewContentModeRedraw;
  tuneView1 = tuneView;
  tuneView2 = newView;
#endif
}

#if __IPHONE_3_2
- (void)dotsChanged
{
  tuneView.tune = tune.dots;
  [tuneView setNeedsDisplay];
}
#endif

- (void)showTune:(Tune *)t
{
  [self showTune:t fromPlayList:nil];
}

- (void)showTune:(Tune *)t fromPlayList:(Playlist *)aPlaylist;
{
#if __IPHONE_3_2
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  appDelegate.currentTune = t.primaryKey;

  [self stopPlaying:self];

  self.tune = t;
  [t hydrate];

  emailButton.enabled = t != nil;
  editButton.enabled = t != nil;
  playButton.enabled = t != nil;

  CGRect bounds;
#if 1//Measuring
  numPages = 1;
  if ( tune ) {
    UIGraphicsBeginImageContext( CGSizeMake( 8, 8 ) );
    numPages = [TuneView drawTune:tune.dots intoContext:UIGraphicsGetCurrentContext() bounds:CGRectMake(0, 0, 8, 8) scale:1.0f];
    if ( numPages < 1 )
      numPages = 1;
    bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, numPages * PaperHeight * kTuneScale );
    UIGraphicsEndImageContext();
  } else
    bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, PaperHeight * kTuneScale );
#else
  bounds = CGRectMake( 0, 0, PaperWidth * kTuneScale, PaperHeight * kTuneScale );
#endif

  TuneView *newView = [[TuneView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 1.0)];
  newView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  newView.scale = 1.0f;

	newView.frame = tuneView.frame;
  newView.tune = t ? [t dots] : nil;
  newView.contentMode = UIViewContentModeRedraw;

  float scale = 1.4f;
#if __IPHONE_3_2
  if ( UIInterfaceOrientationIsLandscape( self.interfaceOrientation ) )
    scale *= 1.35f;
#endif
  newView.scale = scale;

  CGSize contentSize;
  contentSize.width = PaperWidth*kTuneScale * scale;
  contentSize.height = PaperHeight*kTuneScale * scale * numPages;

  CGSize scrollFrameSize = scrollView.bounds.size;
  CGPoint frameOrigin;
  frameOrigin.x = (contentSize.width < scrollFrameSize.width) ? ((scrollFrameSize.width - contentSize.width) / 2) : 0;
  frameOrigin.y = (contentSize.height < scrollFrameSize.height) ? ((scrollFrameSize.height - contentSize.height) / 2) : 0;

  [newView setTransform:CGAffineTransformIdentity];
  [newView setFrame:CGRectMake(frameOrigin.x, frameOrigin.y, contentSize.width, contentSize.height)];
  [scrollView setContentSize:contentSize];

  if ( appDelegate.transitionType != 0 ) {
    if ( appDelegate.transitionType == 3 )
      newView.alpha = 0.0f;
    else if ( appDelegate.transitionType == 2 ) {
      CGRect r = newView.frame;
      r.origin.x -= r.size.width;
      newView.frame = r;
    }
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5f];
  }
  if ( appDelegate.transitionType == 1 )
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:mainView cache:YES];
  else if ( appDelegate.transitionType == 3 ) {
    tuneView.alpha = 0.0f;
    newView.alpha = 1.0f;
  }
  else if ( appDelegate.transitionType == 2 ) {
    CGRect r = newView.frame;
    r.origin.x += r.size.width;
    newView.frame = r;
  }
  [tuneView removeFromSuperview];
	[scrollView addSubview: newView];
  [tuneView release];
  tuneView = newView;
  if ( appDelegate.transitionType != 0 )
    [UIView commitAnimations];
#if PAGING
  self.playlist = aPlaylist;
  tuneView1 = tuneView;
//  [self setPagingMode];
  NSUInteger page = [[self tunes] indexOfObject:tune];
  [self scrollToPage: page];
  currentPage = page;
  pageLabel.alpha = 1.0f;
  pageLabel.text = [NSString stringWithFormat:@"Page %d of %d - %@ - %@", currentPage, [self pageCount], playlist.name, tune.title];
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:1];
  pageLabel.alpha = 0.0f;
	[UIView commitAnimations];
#endif
#endif
}

- (NSString *)currentDots
{
  return self.editing ? editController.text : tune.dots;
}

- (void)showPage:(NSInteger)page
{
  NSArray *tunes = [self tunes];
  if ( page >= 0 && page < [tunes count] ) {
    [self showTune:[tunes objectAtIndex:page] fromPlayList:playlist];
  }
}

- (IBAction)prevTune:(id)sender
{
  [self showPage:currentPage-1 ];
}

- (IBAction)nextTune:(id)sender
{
  [self showPage:currentPage+1 ];
}

- (void)showMusic
{
	if ( showingABC )
    [self editABC];
}

- (void)showABC
{
  [self hideSettings];
	if ( !showingABC )
    [self editABC];
}

- (void)editABC
{
#if __IPHONE_3_2
  editController = [EditABCController alloc];
  [editController initWithNibName:@"EditABC" bundle:nil];
  editController.editTune = tune;
	[self presentModalViewController:editController animated:YES];
  [editController release];
#else
  if ( !editController ) {
    editController = [EditABCController alloc];
    [editController initWithTitle:tune.title];
    editController.text = tune.dots;
    [editController retain];
  }

	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:1];
	[UIView setAnimationTransition:([self.view superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES];
	
	if ( !showingABC ) {
		[editController viewWillAppear:YES];
		[self viewWillDisappear:YES];
		[mainView removeFromSuperview];
		[self.view addSubview:editController.view];
		[self viewDidDisappear:YES];
		[editController viewDidAppear:YES];
    showingABC = YES;
	} else {
    tuneView.tune = editController.text;
    [tuneView setNeedsDisplay];
		[self viewWillAppear:YES];
		[editController viewWillDisappear:YES];
		[editController.view removeFromSuperview];
		[self.view addSubview:mainView];
		[editController viewDidDisappear:YES];
		[self viewDidAppear:YES];
    showingABC = NO;
	}
	[UIView commitAnimations];
#endif
}

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
  [super setEditing:editing animated:animated];
#if __IPHONE_3_2
  self.navigationItem.hidesBackButton = editing;
  if ( editing ) {
    [self.navigationItem setLeftBarButtonItem: abcButton animated:YES];
  } else {
    self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;
  }
#endif

  if ( editing ) {
    [self showABC];
  } else {
    [self showMusic];
    if ( editController.changed ) {
      saveChangesSheet = [[UIActionSheet alloc]
        initWithTitle:[NSString stringWithFormat:@"Save Changes to '%@'?", tune.title]
        delegate:self
#if __IPHONE_3_2
        cancelButtonTitle:@"Don't Save"
        destructiveButtonTitle:@"Save"
#else
        cancelButtonTitle:@"Save"
        destructiveButtonTitle:@"Don't Save"
#endif
        otherButtonTitles:nil
      ];
      [saveChangesSheet showInView:self.view];
    } else {
      [editController release];
      editController = NULL;
    }
  }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
  AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  if ( actionSheet == saveChangesSheet ) {
#if __IPHONE_3_2
    if ( buttonIndex == 2 ) { // Save
#else
    if ( buttonIndex == 1 ) { // Save
#endif
      numTunes = 0;
      parsedTunes = [[NSMutableArray alloc] init];
      [parsedTunes retain];
      TuneParser *parser = [[TuneParser alloc] init];
      parser.delegate = self;
      NSString *dots = editController.text;
      [parser parseString:dots];
      if ( numTunes == 0 ) {
        UIAlertView *alert = [[UIAlertView alloc] 
          initWithTitle: @"Bad ABC" 
          message:@"The ABC does not contain any valid tunes." 
          delegate:nil
          cancelButtonTitle:nil 
          otherButtonTitles:@"OK", nil];
        [alert show];
        [parsedTunes release];
      } else if ( numTunes > 1 ) {
        multipleTunesSheet = [[UIActionSheet alloc]
          initWithTitle:[NSString stringWithFormat:@"Multiple tunes in ABC"]
          delegate:self
          cancelButtonTitle:@"Cancel"
          destructiveButtonTitle:@"Add Extra Tunes"
          otherButtonTitles:nil
        ];
        [multipleTunesSheet showInView:self.view];
      } else {
        Tune *t = (Tune *)[parsedTunes objectAtIndex:0];
        tune.title = t.title;//FIXME-method to do this...
        tune.dots = t.dots;
        tune.rating = t.rating;
        tune.key = t.key;
        tune.numSharps = t.numSharps;
        tune.timeSigNum = t.timeSigNum;
        tune.timeSigDen = t.timeSigDen;
        if ( [tune inDatabase] ) {
          [tune dehydrate];
          [tune hydrate];
        } else
          [appDelegate addTune:tune];
        [parsedTunes release];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"databaseChanged" object:self]; 
      }
    } else { // Don't Save
      tuneView.tune = [tune dots];
      [tuneView setNeedsDisplay];
//      tune.dots = savedDots;
    }
  } else if ( actionSheet == multipleTunesSheet ) {
    if ( buttonIndex == 0 ) {
      Tune *t = (Tune *)[parsedTunes objectAtIndex:0];
      tune.title = t.title;
      tune.dots = t.dots;
      tune.rating = t.rating;
      tune.key = t.key;
      tune.numSharps = t.numSharps;
      tune.timeSigNum = t.timeSigNum;
      tune.timeSigDen = t.timeSigDen;
      if ( [tune inDatabase] )
        [tune dehydrate];
      else
        [appDelegate addTune:tune];

      // Add the extra tunes
      for ( int i = 1; i < [parsedTunes count]; i++ )
        [appDelegate addTune:(Tune *)[parsedTunes objectAtIndex:i]];
      [[NSNotificationCenter defaultCenter] postNotificationName:@"databaseChanged" object:self]; 
    }
    [parsedTunes release];
  }
  [editController release];
  editController = NULL;
}

- (void) parsedTune:(TuneParser *)parser tune:(Tune *)t
{
  numTunes++;
  [parsedTunes addObject:t];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
  return YES;
}

- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning];
}

-(void)dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	[tuneView.delegate release];
  [scrollView retain];
	[tuneView release];
	[playItems release];
	[stopItems release];
  if ( settingsController )
    [settingsController release];
  [abcButton release];
//  [savedDots release];
//  [tunePlayer release];
	[super dealloc];
}

- (IBAction)hideStatusBar {
  [[self navigationController] setNavigationBarHidden:YES animated:YES];
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:0.30];
  scrollView.contentInset = UIEdgeInsetsMake( 0, 0, 0, 0 );
  toolbar.alpha = 0.0;
  [self hideSettings];
	[UIView commitAnimations];
  barsHidden = true;
}

- (IBAction)showStatusBar {
  [[self navigationController] setNavigationBarHidden:NO animated:YES];
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:0.30];
  scrollView.contentInset = UIEdgeInsetsMake( 0, 0, 88, 0 );
  toolbar.alpha = 1.0;
	[UIView commitAnimations];
  barsHidden = false;
}

- (void)viewTapped:(id)sender {
//#if !__IPHONE_3_2
  if ( barsHidden )
    [self showStatusBar];
  else
    [self hideStatusBar];
//#endif
}

- (IBAction)zoomToFit:(id)sender
{
#if __IPHONE_3_2
  if ( UIInterfaceOrientationIsLandscape( self.interfaceOrientation ) )
    tuneView.scale = 1.4f * 1.35f;
  else
    tuneView.scale = 1.4f;
#else
  tuneView.scale = 1.0f;
#endif
  float scale = tuneView.scale * kTuneScale;
  tuneView.transform = CGAffineTransformIdentity;
	tuneView.frame = CGRectMake( 0, 0, PaperWidth*scale, PaperHeight*scale );
	scrollView.contentSize = CGSizeMake( PaperWidth*scale, PaperHeight*scale );
#if __IPHONE_3_2
  scrollView.contentOffset = CGPointMake(0.0f, 0.0f);
#else
  scrollView.contentOffset = CGPointMake(40.0f, 50.0f);
#endif
  [tuneView setNeedsLayout];
  [tuneView setNeedsDisplay];
  [self scrollViewDidEndZooming:scrollView withView:self.view atScale:1.0f];
#if PAGING
  tuneView2.scale = tuneView.scale;
  tuneView2.frame = tuneView.frame;
//	[self setPagingMode];
#endif
}

- (void)viewDoubleTapped:(id)sender {
#if __IPHONE_3_2
//  if ( barsHidden )
//    [self showStatusBar];
//  else
//    [self hideStatusBar];
#else
  [self hideStatusBar];
#endif
  [self zoomToFit:sender];
}

#pragma mark UIViewController delegate methods

- (void)viewWillAppear:(BOOL)animated
{
#if PAGING
//	[self setPagingMode];
#endif
  if ( self.editing )
    [tuneView setNeedsDisplay]; // Force a refresh if we're editing
}

- (void)viewWillDisappear:(BOOL)animated
{
  [self hideSettings];
  if ( tunePlayer )
    [tunePlayer stop];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
#if PAGING
//	if (scrollViewMode != ScrollViewModeZooming)
//		[self setZoomingMode];
//	return tuneView1;
#endif
  return tuneView;
}

#if __IPHONE_3_2
- (void)scrollViewDidEndZooming:(UIScrollView *)sv withView:(UIView *)view atScale:(float)scale
{
  float zoomScale=scrollView.zoomScale;
  float oldScale = tuneView.scale;
  scale *= oldScale;

  tuneView.scale = scale;

  CGSize contentSize=scrollView.contentSize;
  CGPoint newContentOffset=scrollView.contentOffset;
  CGSize oldContentViewSize=[tuneView frame].size;

  float xMult = contentSize.width/oldContentViewSize.width;
  float yMult = contentSize.height/oldContentViewSize.height;

  newContentOffset.x *= xMult;
  newContentOffset.y *= yMult;

  float currentMinZoom = scrollView.minimumZoomScale;
  float currentMaxZoom = scrollView.maximumZoomScale;

  float newMinZoom = currentMinZoom/zoomScale;
  float newMaxZoom = currentMaxZoom/zoomScale;

  [scrollView setMinimumZoomScale:1.0];
  [scrollView setMaximumZoomScale:1.0];
  [scrollView setZoomScale:1.0 animated:NO];

  CGSize scrollFrameSize = sv.bounds.size;
  CGPoint frameOrigin;
  frameOrigin.x = (contentSize.width < scrollFrameSize.width) ? ((scrollFrameSize.width - contentSize.width) / 2) : 0;
  frameOrigin.y = (contentSize.height < scrollFrameSize.height) ? ((scrollFrameSize.height - contentSize.height) / 2) : 0;

  [tuneView setTransform:CGAffineTransformIdentity];
  [tuneView setFrame:CGRectMake(frameOrigin.x, frameOrigin.y, contentSize.width, contentSize.height)];

  scrollView.contentSize=contentSize;
  [scrollView setContentOffset:newContentOffset animated:NO];

  [scrollView setMinimumZoomScale:newMinZoom];
  [scrollView setMaximumZoomScale:newMaxZoom];
 
  [tuneView setNeedsDisplay];
#if PAGING
//	if (scrollView.zoomScale == scrollView.minimumZoomScale)
//		[self setPagingMode];
//	else if (pendingOffsetDelta > 0) {
//		UIView *view = tuneView1;
//		view.center = CGPointMake(view.center.x - pendingOffsetDelta, view.center.y);
//		CGSize pageSize = [self pageSize];
//		scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x - pendingOffsetDelta, scrollView.contentOffset.y);
//		scrollView.contentSize = CGSizeMake(pageSize.width * scrollView.zoomScale, pageSize.height * scrollView.zoomScale);
//		pendingOffsetDelta = 0;
//	}
#endif
}

- (void)scrollViewDidZoom:(UIScrollView *)sv
{
  CGRect innerFrame = tuneView.frame;
  CGRect scrollerBounds = sv.bounds;

  CGPoint scrollViewOffset = sv.contentOffset;

  if ( innerFrame.size.width < scrollerBounds.size.width )
    scrollViewOffset.x = tuneView.center.x - ( scrollerBounds.size.width / 2 );
  if ( innerFrame.size.height < scrollerBounds.size.height )
    scrollViewOffset.y = tuneView.center.y - ( scrollerBounds.size.height / 2 );
  sv.contentOffset = scrollViewOffset;
}
#else
- (void)scrollViewDidEndZooming:(UIScrollView *)sv withView:(UIView *)view atScale:(float)scale
{
  float oldScale = tuneView.scale;
  scale *= oldScale;

#if !__IPHONE_3_2
  // Prior to 3.2 the only way to get the UIScrollView to zoom properly is to destroy and recreate the tune view
  [tuneView removeFromSuperview];
  [tuneView release];

  tuneView = [[TuneView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 1.0)];
  tuneView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  tuneView.tune = [self currentDots];
  tuneView.contentMode = UIViewContentModeRedraw;
#endif
  tuneView.scale = scale;

  CGSize contentSize;
  contentSize.width = PaperWidth*kTuneScale * scale;
  contentSize.height = PaperHeight*kTuneScale * scale * numPages;

  CGSize scrollFrameSize = sv.bounds.size;
  CGPoint frameOrigin;
  frameOrigin.x = (contentSize.width < scrollFrameSize.width) ? ((scrollFrameSize.width - contentSize.width) / 2) : 0;
  frameOrigin.y = (contentSize.height < scrollFrameSize.height) ? ((scrollFrameSize.height - contentSize.height) / 2) : 0;

  [tuneView setTransform:CGAffineTransformIdentity];
  [tuneView setFrame:CGRectMake(frameOrigin.x, frameOrigin.y, contentSize.width, contentSize.height)];
  [sv setContentSize:contentSize];
  [sv setNeedsDisplay];
#if !__IPHONE_3_2
  [sv addSubview:tuneView];
#endif

  [tuneView setNeedsDisplay];
}
#endif

- (IBAction)startPlaying:(id)sender
{
  if ( !tunePlayer )
    tunePlayer = [TunePlayer tunePlayer];

  if ( [tunePlayer playing] ) {
    toolbar.items = stopItems;
    [tunePlayer stop];
  } else {
    toolbar.items = playItems;
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSString *directory = NSTemporaryDirectory();
    NSString *abcPath = [directory stringByAppendingPathComponent:@"tune.abc"];
    NSString *midiPath = [directory stringByAppendingPathComponent:@"tune.mid"];

    NSError *error = NULL;
    if ( [[tune dots] writeToFile:abcPath atomically:false encoding:NSUTF8StringEncoding error:&error] ) {
      const char *argv[] = {
        "abc2midi",
        [abcPath UTF8String],
        appDelegate.guitarChords ? "-GC" : "-NGC",
        "-quiet",
        "-o",
        [midiPath UTF8String],
        NULL
      };
      extern int abc2midi_main(int argc, const char *argv[]);
      abc2midi_main( 6, argv );
      tunePlayer.filePath = midiPath;
      [tunePlayer play];
    }
  }
}

- (void)playerFinished:(id)sender
{
  toolbar.items = stopItems;
}

- (IBAction)stopPlaying:(id)sender
{
  toolbar.items = stopItems;
  [tunePlayer stop];
}

- (IBAction)pausePlaying:(id)sender
{
  [self startPlaying:sender];
}

- (IBAction)rewindPlaying:(id)sender
{
  [tunePlayer stop];
  [tunePlayer play];
}

- (void)finishedPlaying:(id)sender
{
  toolbar.items = stopItems;
}

- (IBAction)showSettings:(id)sender
{
  if ( showingSettings ) {
    [self hideSettings];
  } else {
    if ( !tunePlayer )
      tunePlayer = [TunePlayer tunePlayer];

    if ( !settingsController )
      settingsController = [[TuneSettingsController alloc] initWithPlayer:tunePlayer];
#if __IPHONE_3_2
    settingsController.contentSizeForViewInPopover = settingsController.view.bounds.size;
    [self presentPopoverController:sender controller:settingsController];
#else
    CGSize s1 = self.view.bounds.size;
    CGSize s2 = settingsController.view.bounds.size;
    [settingsController.view setFrame:CGRectOffset(settingsController.view.bounds, (s1.width-s2.width)/2, (s1.height-s2.height-44)/2)];
		settingsController.view.alpha = 0.0;
    [self.view addSubview:settingsController.view];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.40];
		settingsController.view.alpha = 1.0;
    [UIView commitAnimations];
#endif
    showingSettings = YES;
  }
}

- (void)hideSettings
{
#if !__IPHONE_3_2
  if ( settingsController && showingSettings ) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.40];
		settingsController.view.alpha = 0.0;
    [UIView commitAnimations];
  }
#endif
  showingSettings = NO;
}

- (IBAction)emailTune:(id)sender
{
	Class mailClass = NSClassFromString(@"MFMailComposeViewController");
	if (mailClass != nil)
	{
		if ([mailClass canSendMail])
			[self displayComposerSheet];
		else
			[self launchMailAppOnDevice];
	}
	else
		[self launchMailAppOnDevice];
}

#if __IPHONE_3_2
- (IBAction)tunesPressed:(id)sender
{
#if 1
  static MainViewController *controller;
  static UINavigationController *navigationController;
  if ( !controller ) {
    controller = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
    controller.playlist = nil;
    navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  }
  navigationController.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:navigationController];
#else
  MainViewController *controller = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
  controller.playlist = nil;
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  navigationController.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:navigationController];
#endif
}

- (IBAction)tunebooksPressed:(id)sender
{
#if 1
  static PlaylistViewController *controller;
  static UINavigationController *navigationController;
  if ( !controller ) {
    controller = [[PlaylistViewController alloc] initWithNibName:@"PlaylistView" bundle:nil];
    [controller databaseChanged:self];
    navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  }
  navigationController.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:navigationController];
#else
  PlaylistViewController *controller = [[PlaylistViewController alloc] initWithNibName:@"PlaylistView" bundle:nil];
  [controller databaseChanged:self];
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  navigationController.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:navigationController];
  [navigationController release];
  [controller release];
#endif
}

- (IBAction)searchPressed:(id)sender
{
  SearchViewController *controller = [[SearchViewController alloc] initWithNibName:@"SearchView" bundle:nil];
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
  navigationController.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:navigationController];
  [navigationController release];
}

- (IBAction)managePressed:(id)sender
{
  ManageTunesController *controller = [[ManageTunesController alloc] initWithNibName:@"ManageTunes" bundle:nil];
  controller.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:controller];
  [controller release];
}

- (IBAction)settingsPressed:(id)sender
{
  SettingsController *controller = [[SettingsController alloc] initWithNibName:@"Settings" bundle:nil];
  controller.contentSizeForViewInPopover = CGSizeMake(320,480);
  [self presentPopoverController:sender controller:controller];
  [controller release];
}

- (IBAction)editPressed:(id)sender
{
  [self dismissPopoverController];
  [self setEditing:YES animated:YES];
}
#endif

#pragma mark -
#pragma mark Compose Mail

-(void)displayComposerSheet 
{
	MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
	picker.mailComposeDelegate = self;
	
	[picker setSubject:[@"Tune: " stringByAppendingString:tune.title]];

	NSString *emailBody = tune.dots;
	[picker setMessageBody:emailBody isHTML:NO];
  NSData *attachment = [TuneView pdfDataForTune:tune.dots];
	[picker addAttachmentData:attachment mimeType:@"application/pdf" fileName:@"tune.pdf"];
	
	[self presentModalViewController:picker animated:YES];
  [picker release];
}

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error 
{	
	switch (result)
	{
  case MFMailComposeResultCancelled:
    break;
  case MFMailComposeResultSaved:
    break;
  case MFMailComposeResultSent:
    {
    UIAlertView *alert = [[UIAlertView alloc] 
      initWithTitle: @"Success" 
      message:@"Your tune has been sent." 
      delegate:nil
      cancelButtonTitle:nil 
      otherButtonTitles:@"OK", nil];
    [alert show];
    }
    break;
  case MFMailComposeResultFailed:
  default:
    {
    UIAlertView *alert = [[UIAlertView alloc] 
      initWithTitle: @"Unable to send email" 
      message:@"Please make sure that email is configured correctly." 
      delegate:nil
      cancelButtonTitle:nil 
      otherButtonTitles:@"OK", nil];
    [alert show];
    }
    break;
	}
	[self dismissModalViewControllerAnimated:YES];
}


#pragma mark -
#pragma mark Workaround

-(void)launchMailAppOnDevice
{
	NSString *recipients = @"mailto:?&subject=Tune: ";
	NSString *body = [@"&body=" stringByAppendingString:tune.dots];
	
	NSString *email = [NSString stringWithFormat:@"%@%@%@", recipients, tune.title, body];
	email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
	
	[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}

#if __IPHONE_3_2
- (void)actionSheet:(UIActionSheet*)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
  if( activeActionSheet == actionSheet ) {
    activeActionSheet = nil;
    activeBarButtonItem = nil;
  }
}

- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController*)popoverController
{
  if( activePopoverController == popoverController ) {
    activePopoverController = nil;
    activeBarButtonItem = nil;
  }
  return YES;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
  if( activePopoverController )
  {
    if( activeBarButtonItem )
    {
      rotateViewController = [activePopoverController contentViewController];
      [rotateViewController retain];
      rotatePassthroughViews = [activePopoverController passthroughViews];
      [rotatePassthroughViews retain];
      rotateBarButtonItem = activeBarButtonItem;
    }
    [activePopoverController dismissPopoverAnimated:YES];
    activePopoverController = nil;
  }
  else if( activeActionSheet )
  {
    if( activeBarButtonItem )
    {
      rotateActionSheet = activeActionSheet;
      [rotateActionSheet retain];
      rotateBarButtonItem = activeBarButtonItem;
    }
    [activeActionSheet dismissWithClickedButtonIndex:-1 animated:YES];
    activeActionSheet = nil;
  }
  activeBarButtonItem = nil;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  [super didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation];
  if( rotateBarButtonItem )
  {
    activeBarButtonItem = rotateBarButtonItem;
    rotateBarButtonItem = nil;
  }
  if( rotateViewController )
  {
    if( activeBarButtonItem )
    {
      activePopoverController = [[UIPopoverController alloc] initWithContentViewController:rotateViewController];
      if( rotatePassthroughViews )
      {
        [activePopoverController setPassthroughViews:rotatePassthroughViews];
      }
      [activePopoverController presentPopoverFromBarButtonItem:activeBarButtonItem
          permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    }
    [rotateViewController release];
    rotateViewController = nil;
    [rotatePassthroughViews release];
    rotatePassthroughViews = nil;
  }
  else if( rotateActionSheet )
  {
    if( activeBarButtonItem )
    {
      activeActionSheet = rotateActionSheet;
      [rotateActionSheet showFromBarButtonItem:activeBarButtonItem animated:YES];
    }
    [rotateActionSheet release];
    rotateActionSheet = nil;
  }
  [self zoomToFit:self];
}

- (void)presentMyActionSheet:(id)sender
{
//  if( activeActionSheet || activePopoverController )
//  {
//    if( activeActionSheet )
//    {
//      [activeActionSheet dismissWithClickedButtonIndex:-1 animated:YES];
//      activeActionSheet = nil;
//    }
//    if( activePopoverController )
//    {
//      [activePopoverController dismissPopoverAnimated:YES];
//      activePopoverController = nil;
//    }
//    activeBarButtonItem = nil;
//  }
//  activeActionSheet =
//  [[UIActionSheet alloc] initWithTitle:nil
//                              delegate:self
//                     cancelButtonTitle:nil
//                destructiveButtonTitle:nil
//                     otherButtonTitles:nil];
//  [actionSheet addButtonWithTitle:@"Button 1"];
//  [actionSheet addButtonWithTitle:@"Button 2"];
//  activeBarButtonItem = sender;
//  [actionSheet showFromBarButtonItem:sender animated:YES];
}

- (void)presentPopoverController:(UIBarButtonItem *)item controller:(UIViewController*)controller
{
  [self dismissPopoverController];
  activePopoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
  [activePopoverController setDelegate:self];
  activeBarButtonItem = item;
  [activePopoverController setPassthroughViews:[NSArray arrayWithObjects:toolbar, nil]];
  [activePopoverController presentPopoverFromBarButtonItem:item
      permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

- (IBAction)dismissPopoverController
{
  if ( activePopoverController )
    [activePopoverController dismissPopoverAnimated:YES];
}
#endif

@end
