#import <appkit/Application.h>
#import <appkit/Window.h>
#import <appkit/Menu.h>
#import <appkit/MenuCell.h>
#import <appkit/Text.h>
#import <appkit/Form.h>
#import <soundkit/Sound.h>
#import <ldsyms.h>
#import <sys/loader.h>
#import <strings.h>
#import <libc.h>
#import "pathutil.h"
#import "a3DViewerView.h"
#import "CubeView.h"

static struct mach_header  *header;	// The header used for loading
static id    customSubmenu;		// Submenu handle for possible extension

static id    inspectorPanel;
static id    fileName;
static id    parameterForm;
static id    recordButton;
static id    stopButton;
static id    playButton;
static id    deleteButton;
static id    tmpSound;

@implementation a3DViewerView

+ setCustomComponentData:(struct mach_header *)hd customMenu:(id)subMenu
{
    id  box;
    id  mCell;
    id  classObj;
    header = hd;
    customSubmenu = subMenu;
    mCell = [customSubmenu addItem:"3D Viewer"
                           action:@selector(showAlert)
                           keyEquivalent:0];
    classObj = [[a3DViewerView alloc] init];
    [mCell setTarget:classObj];
    [customSubmenu display];
    
    inspectorPanel = [NXApp loadNibSection:"Inspector.nib" owner:classObj
                                           withNames:YES fromHeader:header];
    box = NXGetNamedObject("3DFileBox", inspectorPanel);
    fileName = NXGetNamedObject("3DFileName", box);
    box = NXGetNamedObject("3DParameterBox", inspectorPanel);
    parameterForm = NXGetNamedObject("3DForm", box);
    [parameterForm setAction:@selector(setPhi) at:0];
    [parameterForm setAction:@selector(setTheta) at:1];
    [parameterForm setAction:@selector(setInvdist) at:2];
    
    box = NXGetNamedObject("3DSoundButtonBox", inspectorPanel);
    recordButton = NXGetNamedObject("3DRecordSoundButton", box);
       [recordButton setAction:@selector(recordSound:)];
    stopButton = NXGetNamedObject("3DStopSoundButton", box);
       [stopButton setAction:@selector(stopSound:)];
    playButton = NXGetNamedObject("3DPlaySoundButton", box);
       [playButton setAction:@selector(playSound:)];
    deleteButton = NXGetNamedObject("3DDeleteSoundButton", box);
       [deleteButton setAction:@selector(deleteSound:)];
    tmpSound = 0x0;
    return classObj;
}

- (void) showAlert
{
    NXRunAlertPanel(NULL, "Custom Menu Activated", NULL, NULL, NULL);
}

- initCustomComponent
{    
    self = [super init];
    _3Dpanel = [NXApp loadNibSection:"3DViewer.nib" owner:self
                                     withNames:YES fromHeader:header];
    _3DcontentView = [_3Dpanel contentView];
    
    _3DcubeView = NXGetNamedObject("3DCubeView" , _3Dpanel);
    [_3DcubeView setmachHeader:header];
    [_3DcubeView setController:self];
    
    [_3Ddatasets setTarget:self];
    [_3Ddatasets setAction:@selector(openData:)];
      
    return _3DcontentView;
}

- recordSound:sender
{
    if( !tmpSound ) tmpSound = [Sound new];
    [tmpSound setDelegate:self];
    [tmpSound record];
    return self;
}

- playSound:sender
{
    if( tmpSound ) [tmpSound play];
    else
    [playButton setState:0];
    return self;
}

- didPlay:sender
{
    [playButton setState:0];
    return self;
}

- didRecord:sender
{
    [recordButton setState:0];
    [_3DcubeView setViewSound:tmpSound];
    return self;
}

- stopSound:sender
{
    if( tmpSound ) [tmpSound stop];
    return self;
}

- deleteSound:sender
{
    [_3DcubeView deleteViewSound];
    return self;
}

- inspectCustomComponent
{
    [inspectorPanel makeKeyAndOrderFront:self];
    [self refreshInspectorPanel];
    return self;
}

- (void)refreshInspectorPanel
{
    int  index;
    if( [inspectorPanel isVisible] ) {
       [recordButton setTarget:self];
       [stopButton setTarget:self];
       [playButton setTarget:self];
       [deleteButton setTarget:self];
       [inspectorPanel orderFront:self];
       if( [_3DcubeView currentDataFile] )
          [fileName setStringValue:basename([_3DcubeView currentDataFile])];
       [parameterForm setFloatValue:[_3DcubeView readPhi] at:0];
       [parameterForm setFloatValue:[_3DcubeView readTheta] at:1];
       [parameterForm setFloatValue:[_3DcubeView readInvdist] at:2];
       for( index=0; index<3; index++ )
          [parameterForm setTarget:self at:index];
    }
}

- (void)setPhi
{
    if( [_3DcubeView writePhi:[parameterForm floatValueAt:0]] )
       [parameterForm setFloatValue:[_3DcubeView readPhi] at:0];;
    [parameterForm selectTextAt:0];
}

- (void)setTheta
{
    if( [_3DcubeView writeTheta:[parameterForm floatValueAt:1]] )
       [parameterForm setFloatValue:[_3DcubeView readTheta] at:1];;
    [parameterForm selectTextAt:1];
}

- (void)setInvdist
{
    if( [_3DcubeView writeInvdist:[parameterForm floatValueAt:2]] )
       [parameterForm setFloatValue:[_3DcubeView readInvdist] at:2];;
    [parameterForm selectTextAt:2];
}

- openData:sender
{
    [_3DcubeView openData:sender];
    [self perform:@selector(displayAndFlush:) with:self
                            afterDelay:1 cancelPrevious:YES];
    return self;
}

- (void) displayAndFlush:sender
{
    [[_3DcontentView window] disableFlushWindow];
    [[_3DcontentView window] display];
    [[_3DcontentView window] reenableFlushWindow];
    [[_3DcontentView window] flushWindowIfNeeded];
    [self resetFirstResponder:_3DcubeView];
}

- setViews:(id)cv
{
    _3DcubeView = cv;
    _3DcontentView = [cv superview];
    return self;
}

- (void)resetFirstResponder:(id)frv
{
    id  vt = [_3DcontentView superview];
    
    if ( [vt isKindOf:[Text class]] )
        [vt textDidGetKeys:vt isEmpty:NO];
    [[frv window] makeFirstResponder:frv];
    [self refreshInspectorPanel];
}

- free
{
    if( tmpSound ) [tmpSound free];
    return [super free];
}

- write:(NXTypedStream *)stream
{
    [super write:stream];
    return self;
}

- read:(NXTypedStream *)stream
{
    [super read:stream];
    return self;
}

- awake
{
    [super awake];
    return self;
}

@end
