//
//  DragFilterWindowController.m
//  LaTeXiT
//
//  Created by Pierre Chatelier on 08/05/10.
//  Copyright 2005-2016 Pierre Chatelier. All rights reserved.
//

#import "DragFilterWindowController.h"

#import "AppController.h"
#import "DragThroughButton.h"
#import "NSButtonPalette.h"
#import "PreferencesController.h"
#import "Utils.h"

@interface DragFilterWindowController (PrivateAPI)
-(void) updateAnimation:(NSTimer*)timer;
-(void) notified:(NSNotification*)notification;
@end

@implementation DragFilterWindowController

-(id) init
{
  if ((!(self = [super initWithWindowNibName:@"DragFilterWindowController"])))
    return nil;
  self->animationDurationIn  = .33;
  self->animationDurationOut = .10;
  return self;
}
//end init

-(void) dealloc
{
  [self->animationTimer invalidate];
  [self->animationTimer release];
  [self->animationStartDate release];
  [self->buttonPalette release];
  [super dealloc]; 
}
//end dealloc

-(void) awakeFromNib
{
  [self->dragFilterViewLabel setStringValue:NSLocalizedString(@"Drag through areas to change export type", @"Drag through areas to change export type")];
  self->buttonPalette = [[NSButtonPalette alloc] init];
  [self->buttonPalette setExclusive:YES];
  NSEnumerator* enumerator = [[self->dragFilterButtonsView subviews] objectEnumerator];
  NSView* view = nil;
  while((view = [enumerator nextObject]))
  {
    if ([view isKindOfClass:[NSButton class]])
      [self->buttonPalette add:(NSButton*)view];
  }//end while((view = [enumerator nextObject]))
  [self->closeButton setShouldBlink:NO];
  [self->closeButton setDelay:.05];

  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_PDF_NOT_EMBEDDED_FONTS] setTitle:
    NSLocalizedString(@"PDF w.o.f.", @"PDF w.o.f.")];

  [[self->buttonPalette buttonWithTag:[[PreferencesController sharedController] exportFormatCurrentSession]] setState:NSOnState];

  BOOL isPdfToSvgAvailable = [[AppController appController] isPdfToSvgAvailable];
  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_SVG] setEnabled:isPdfToSvgAvailable];
  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_SVG] setToolTip:isPdfToSvgAvailable ? nil :
    [NSString stringWithFormat:NSLocalizedString(@"%@ is required", @"%@ is required"), @"pdf2svg"]];
  
  BOOL isPerlWithLibXMLAvailable = [[AppController appController] isPerlWithLibXMLAvailable];
  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_MATHML] setEnabled:isPerlWithLibXMLAvailable];
  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_MATHML] setToolTip:isPerlWithLibXMLAvailable ? nil :
    NSLocalizedString(@"The XML::LibXML perl module must be installed", @"The XML::LibXML perl module must be installed")];

  [[self->buttonPalette buttonWithTag:EXPORT_FORMAT_TEXT] setTitle:NSLocalizedString(@"Text", @"Text")];
  
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notified:) name:DragThroughButtonStateChangedNotification object:nil];
}
//end awakeFromNib

-(void) setWindowVisible:(BOOL)visible withAnimation:(BOOL)animate
{
  NSPoint mouseLocation = [NSEvent mouseLocation];
  [self setWindowVisible:visible withAnimation:animate atPoint:mouseLocation];
}
//end setWindowVisible:withAnimation:

-(void) setWindowVisible:(BOOL)visible withAnimation:(BOOL)animate atPoint:(NSPoint)point
{
  [self setWindowVisible:visible withAnimation:animate atPoint:point isHintOnly:YES];
}
//end setWindowVisible:withAnimation:atPoint:

-(void) setWindowVisible:(BOOL)visible withAnimation:(BOOL)animate atPoint:(NSPoint)point isHintOnly:(BOOL)isHintOnly
{
  if (visible)
  {
    NSWindow* screenWindow = [NSApp keyWindow];
    screenWindow = screenWindow ? screenWindow: [NSApp mainWindow];
    NSRect screenVisibleFrame = [(!screenWindow ? [NSScreen mainScreen] : [screenWindow screen]) visibleFrame];
    NSWindow* window = [self window];
    NSRect windowFrame = [window frame];
    NSPoint newFrameOrigin = !isHintOnly ? point : NSMakePoint(point.x-windowFrame.size.width/2, point.y+32);
    if (isHintOnly)
    {
      newFrameOrigin.x = MAX(0, newFrameOrigin.x);
      newFrameOrigin.x = MIN(screenVisibleFrame.size.width-windowFrame.size.width, newFrameOrigin.x);
      newFrameOrigin.y = MAX(0, newFrameOrigin.y);
      newFrameOrigin.y = MIN(screenVisibleFrame.size.height-windowFrame.size.height, newFrameOrigin.y);
    }//end if (isHintOnly)
    self->fromFrameOrigin = [[self window] isVisible] ? [window frame].origin : newFrameOrigin;
    self->toFrameOrigin = newFrameOrigin;
    [[self window] setFrameOrigin:self->fromFrameOrigin];
    [self->animationStartDate release];
    self->animationStartDate = [[NSDate alloc] init];
    [self->animationTimer invalidate];
    [self->animationTimer release];
    self->animationTimer = nil;
    self->animationStartAlphaValue = ![[self window] isVisible] ? 0 : [[self window] alphaValue];
    [[self window] setAlphaValue:self->animationStartAlphaValue];
    [self showWindow:self];
    if (animate)
      self->animationTimer = [[NSTimer scheduledTimerWithTimeInterval:1./25. target:self selector:@selector(updateAnimation:) userInfo:[NSNumber numberWithBool:visible] repeats:YES] retain];
    else
      [[self window] setAlphaValue:1];
  }
  else// if (!visible)
  {
    [self->animationStartDate release];
    self->animationStartDate = [[NSDate alloc] init];
    [self->animationTimer invalidate];
    [self->animationTimer release];
    self->animationTimer = nil;
    if (animate)
      self->animationTimer = [[NSTimer scheduledTimerWithTimeInterval:1./25. target:self selector:@selector(updateAnimation:) userInfo:[NSNumber numberWithBool:visible] repeats:YES] retain];
    else
      [[self window] close];
  }
}
//end setVisible:withAnimation:atPoint:isHintOnly:

-(void) updateAnimation:(NSTimer*)timer
{
  NSTimeInterval timeElapsed = !self->animationStartDate ? 0. :
    [[NSDate date] timeIntervalSinceDate:self->animationStartDate];
  BOOL toVisible = [[timer userInfo] boolValue];
  NSTimeInterval animationDuration = toVisible ? self->animationDurationIn : self->animationDurationOut;
  timeElapsed = Clip_d(0., timeElapsed, animationDuration);
  double evolution = !animationDuration ? 1. : Clip_d(0., timeElapsed/animationDuration, 1.);
  if (toVisible)
    [[self window] setAlphaValue:(1-evolution)*self->animationStartAlphaValue+evolution*1.];
  else
    [[self window] setAlphaValue:(1-evolution)*self->animationStartAlphaValue+evolution*0.];
  NSPoint currentFrameOrigin = NSMakePoint((1-evolution)*fromFrameOrigin.x+evolution*toFrameOrigin.x,
                                           (1-evolution)*fromFrameOrigin.y+evolution*toFrameOrigin.y);
  [[self window] setFrameOrigin:currentFrameOrigin];
  if (evolution >= 1)
  {
    self->fromFrameOrigin = [[self window] frame].origin;
    if (!toVisible)
      [[self window] close];
  }//end if (evolution >=1)
}
//end updateAnimation:

-(void) notified:(NSNotification*)notification
{
  if ([[notification name] isEqualToString:DragThroughButtonStateChangedNotification])
  {
    DragThroughButton* dragThroughButton = [notification object];
    if ([dragThroughButton state] == NSOnState)
    {
      int tag = [dragThroughButton tag];
      if (tag < 0)
        [self setWindowVisible:NO withAnimation:YES];
      else//if (tag >= 0)
      {
        [[PreferencesController sharedController] setExportFormatCurrentSession:(export_format_t)tag];
        [self dragFilterWindowController:self exportFormatDidChange:[[PreferencesController sharedController] exportFormatCurrentSession]];
      }//end if (tag >= 0)
    }//end if ([dragThroughButton state] == NSOnState)
  }//end if ([[notification name] isEqualToString:DragThroughButtonStateChangedNotification])
}
//end notified:

-(id) delegate
{
  return self->delegate;
}
//end delegate

-(void) setDelegate:(id)value
{
  self->delegate = value;
}
//end setDelegate:

-(void) dragFilterWindowController:(DragFilterWindowController*)dragFilterWindowController exportFormatDidChange:(export_format_t)exportFormat
{
  if (self->delegate && [self->delegate respondsToSelector:@selector(dragFilterWindowController:exportFormatDidChange:)])
    [self->delegate dragFilterWindowController:self exportFormatDidChange:exportFormat];
}
//end dragFilterWindowController:exportFormatDidChange:

@end
