package draggablemp3player;

import javafx.animation.*;
import javafx.stage.*;
import javafx.scene.input.*;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.text.*;
import javafx.scene.media.*;
import javafx.scene.effect.*;

var stage:Stage;

var isApplet = "true".equals(FX.getArgument("isApplet") as String);
var inBrowser = isApplet;
var draggable = AppletStageExtension.appletDragSupported;
var dragTextVisible = bind inBrowser and draggable and dragRect.hover;

var homePage = "http://javafx.com/samples/DraggableMP3Player/index.html";
var baseURL = "http://sun.edgeboss.net/download/sun/javafx_music/";

var artist = "La Bonne Soupe";
var album = "lbs album";

var edmonton_cover = Image { url: "{__DIR__}covers/edmonton.jpg" backgroundLoading: true};
var forward_cover  = Image { url: "{__DIR__}covers/forward.png"  backgroundLoading: true};
var scottish_cover = Image { url: "{__DIR__}covers/scottish.jpg" backgroundLoading: true};
var literary_cover = Image { url: "{__DIR__}covers/literary.png" backgroundLoading: true};

var playlist:Playlist = Playlist {
    songs: [
        Song {
            filename: "09_oaf_king__again.mp3"
            name: "Oaf King, Again" album: "Literary Gentlemen"
            artist: artist baseURL: baseURL cover: literary_cover
        }
        Song {
            filename: "10_fool_conditioning_our_grannie_liu.mp3"
            name: "Fool Conditioning (Our Grannie Liu)" album: "Literary Gentlemen"
            artist: artist baseURL: baseURL cover: literary_cover
        }
        Song {
            filename: "13_delusion.mp3"
            name: "Delusion" album: "Literary Gentlemen"
            artist: artist baseURL: baseURL cover: literary_cover
        }
        Song {
            filename: "01_nana__girl_from_hungary.mp3"
            name: "Nana, Girl From Hungary" album: "Scottish Insufficiency"
            artist: artist baseURL: baseURL cover: scottish_cover
        }
        Song {
            filename: "04_im_cold_and_i_want_to_go_home.mp3"
            name: "I'm Cold And I Want To Go Home" album: "Scottish Insufficiency"
            artist: artist baseURL: baseURL cover: scottish_cover
        }
        Song {
            filename: "01_good_day_things_can_change.mp3"
            name: "Good Day Things Can Change" album: "Edmonton Tussle"
            artist: artist baseURL: baseURL cover: edmonton_cover
        }
        Song {
            filename: "02_i_guess__amen.mp3"
            name: "I Guess, Amen" album: "Edmonton Tussle"
            artist: artist baseURL: baseURL cover: edmonton_cover
        }
        Song {
            filename: "04_flash_flood_participant.mp3"
            name: "Flash Flood Participant" album: "Forward To The Forward People"
            artist: artist baseURL: baseURL cover: forward_cover
        }
        Song {
            filename: "09_ellowen_deeowen.mp3"
            name: "Ellowen Deeowen" album: "Forward To The Forward People"
            artist: artist baseURL: baseURL cover: forward_cover
        }
    ]
};

function stopCurrentSong():Void {
    mediaPlayer.stop();
    mediaPlayer.media = null;
    if (playlist.currentPlayingSong != null) {
        playlist.currentPlayingSong.closeMedia();
    }
}

function playCurrentSong():Void {
    playlist.currentPlayingSong = playlist.songs[playlist.currentSong];
    mediaPlayer.media = playlist.currentPlayingSong.getMedia();
    mediaPlayer.play();
}

FX.addShutdownAction(function() { stopCurrentSong(); });

var mediaPlayer:MediaPlayer = MediaPlayer {
    volume: 0.5
    autoPlay: false
    onError: function(e:MediaError) {
        println("got a MediaPlayer error : {e.cause} {e}");
        stopCurrentSong();
    }
    onEndOfMedia: function() {
        println("reached end of media");
        stopCurrentSong();
        playlist.currentSong++;
        playCurrentSong();
    }
};


var playlist_bg = ImageView { id: "playlist_bg" opacity: 1.0 visible: true
    translateX: 198
    translateY: 120
    image: Image { url: "{__DIR__}images/MP3_handoff_playlist.png" }
};

var song_info_current_song:Song = null;
var song_info_popup:Group = Group {
    visible: false
    translateX: 250
    translateY: 40
    blocksMouse: true
    content: [
        Rectangle {
            width: 220 height: 290
            fill: Color.BLACK
            arcWidth: 20
            arcHeight: 20
            stroke: Color.rgb(50,50,50)
        },
        ImageView { x: 5 y: 5 image: Image { url: "{__DIR__}images/MP3_handoff_drag_close.png" }
            onMousePressed: function(e) {
                song_info_popup.visible = false;
            }
        },
        ImageView { x: 10 y: 46 image: bind song_info_current_song.cover },
        Text { x: 10 y: 40 content: bind song_info_current_song.artist fill: Color.WHITE },
        Text { x: 10 y: 260 content: bind song_info_current_song.album fill: Color.WHITE },
        Text { x: 10 y: 275 content: bind song_info_current_song.name fill: Color.WHITE },
    ]
}

var playlist_text = Group {
    content: for(song in playlist.songs) {
        var i_image = ImageView { x: 357 image: Image { url: "{__DIR__}images/MP3_handoff_i.png" } };
        var i_overlay_image = ImageView { x: 353 y:-2 opacity: 0.0 image: Image { url: "{__DIR__}images/MP3_handoff_Group_1_copy_2.png" } 
            onMouseClicked: function(e) {
                song_info_current_song = song;
                song_info_popup.visible = true;
            }
        };
        RolloverBehavior { target: i_overlay_image };

        Group {
            translateX: 210
            translateY: 15 * indexof song + 190
            content: [
                ImageView {
                    x: 0
                    visible: bind (playlist.currentSong == indexof song)
                    image: Image { url: "{__DIR__}images/MP3_handoff_playlist_volume.png" }
                },
                Text {
                    x: 20
                    y: 8
                    fill: Color.WHITE
                    content: "{1 + indexof song}  {song.album} - {song.name}"
                    font: Font { size: 11 name: "Arial" }
                },
                i_image,
                i_overlay_image,

            ]
        }
    }
};

var playlist_innerGroup = Group {
    translateY: -230
    content: [playlist_bg,  playlist_text]
};
var playlist_group = Group {
    content: playlist_innerGroup
    clip: Rectangle { x: 200 y: 100 width: 400 height: 300 }
};

var playlist_reveal = Timeline {
    rate: -1.0
    keyFrames: [
        at (0s)   { playlist_innerGroup.translateY => -230 },
        at (0.4s) { playlist_innerGroup.translateY => 0 }
    ]
};


// the body of the player
var player_normal = ImageView { id: "player_normal"
    opacity: 1.0  visible: true
    x: 83 y: 29
    image: Image { url: "{__DIR__}images/MP3_handoff_player_normal.png" },
};




// the various button rollovers
var fx_rollover:ImageView = ImageView { id: "fx_rollover"
    opacity: 0.0 visible: true
    x: 196 y: 91
    image: Image { url: "{__DIR__}images/MP3_handoff_fx_rollover.png" },
    onMouseClicked: function(e) {
        println("going to the fx homepage");
        AppletStageExtension.showDocument(homePage);
    }
};
RolloverBehavior { target: fx_rollover };

var playlist_rollover:ImageView = ImageView { id: "playlist_rollover"
    opacity: 0.0 visible: true
    x: 115 y: 157
    blocksMouse:true
    image: Image { url: "{__DIR__}images/MP3_handoff_playlist_rollover.png" },
    onMousePressed: function(e) {
        playlist_reveal.rate *= -1.0;
        playlist_reveal.play();
    }
};
RolloverBehavior { target: playlist_rollover };


var playBack = ImageView { id: "playBack"
    opacity: 0.0 visible: true
    x: 99 y: 104
    image: Image { url: "{__DIR__}images/MP3_handoff_playBack.png" },
    onMousePressed: function(e) {
        var paused = mediaPlayer.paused;
        if (not paused) {
            stopCurrentSong();
            playlist.currentSong--;
            playCurrentSong();
        } else {
            playlist.currentSong--;
        }
    }
};
RolloverBehavior { target: playBack };


var playForward = ImageView { id: "playFoward"
    opacity: 0.0 visible: true
    x: 165 y: 107
    image: Image { url: "{__DIR__}images/MP3_handoff_playFoward.png" },
    onMousePressed: function(e) {
        var paused = mediaPlayer.paused;
        if (not paused) {
            stopCurrentSong();
            playlist.currentSong++;
            playCurrentSong();
        } else {
            playlist.currentSong++;
        }
    }
};
RolloverBehavior { target: playForward };


var stop = ImageView { id: "stop"
    opacity: 0.0 visible: true
    x: 116 y: 88
    image: Image { url: "{__DIR__}images/MP3_handoff_stop.png" },
    onMousePressed: function(e) {
        mediaPlayer.stop();
    }
};
RolloverBehavior { target: stop };


var play_normal_image = Image { url: "{__DIR__}images/play.png" };
var play_rollover_image = Image { url: "{__DIR__}images/play_selected.png" };
var pause_normal_image = Image { url: "{__DIR__}images/pause.png" };
var pause_rollover_image = Image { url: "{__DIR__}images/pause_selected.png" };
var play_rollover:ImageView = ImageView { id: "play_rollover"
    opacity: 1.0 visible: true
    x: 122 y: 114
    image: bind if (not mediaPlayer.paused) {
        if (play_rollover.hover) { pause_rollover_image } else { pause_normal_image }
    } else {
        if (play_rollover.hover) { play_rollover_image } else { play_normal_image }
    }
    onMousePressed: function(e) {
        if (playlist.currentPlayingSong != playlist.songs[playlist.currentSong]) {
            stopCurrentSong();
            playCurrentSong();
        } else {
            if (mediaPlayer.paused) {
                mediaPlayer.play();
            } else {
                mediaPlayer.pause();
            }
        }
    }
};

var drag_opacity = 0.0;
var drag_close_rollover = Image { url: "{__DIR__}images/close_rollover.png" };
var drag_close_normal = Image { url: "{__DIR__}images/close.png" };
var drag_out_rollover = Image { url: "{__DIR__}images/dragOut_rollover.png" };
var drag_out_normal = Image { url: "{__DIR__}images/dragOut.png" };

var drag_closers = Group {
    opacity: bind drag_opacity;
    content:[ 
        ImageView { x: 541 y: 44 image: drag_close_normal  visible: bind not inBrowser },
        ImageView { x: 541 y: 44 image: drag_out_normal  visible: bind inBrowser and draggable  },
        Rectangle { x: 541 y: 44 width: 10 height: 10 fill: Color.TRANSPARENT
            onMouseClicked: function(e:MouseEvent):Void { stage.close(); }
        }
    ]
    };

var dragAreaFader = Timeline {
    keyFrames: [
        at (0s)   { drag_opacity => 0.0 },
        at (0.2s) { drag_opacity => 1.0 },
    ]
};

var dragRect:Rectangle = Rectangle {
    x: 155 y: 30 width: 420 height: 40 fill: Color.TRANSPARENT
    onMouseEntered: function(e) {
        dragAreaFader.rate = 1.0;
        dragAreaFader.play();
    }
    onMouseExited: function(e) {
        dragAreaFader.rate = -1.0;
        dragAreaFader.play();
    }
};

var can_drag_me:ImageView = ImageView { id: "can_drag_me"
    opacity: bind drag_opacity
    visible: true
    x: 83 y: 29
    image: Image { url: "{__DIR__}images/MP3_handoff_can_drag_me.png" },
    onMouseDragged: function(e) {
        stage.x += e.dragX;
        stage.y += e.dragY;
    }
};

var can_drag_me_text:Text = Text { content: "You can drag me out of the browser"
    fill: Color.WHITE
    font: Font { size: 12 embolden: true name: "Arial"}
    effect: DropShadow { offsetX: 0 offsetY: 1 color:Color.BLACK spread: 0.5 radius: 14} 
    opacity: bind drag_opacity
    visible: bind dragTextVisible
    y: 60
    x: 165
};



// the time control slider
var time_control_length = 240.0;
var time_control_xoff = 210;
var currentTime = bind
    if (mediaPlayer.media != null and
        mediaPlayer.media.duration != null and
        mediaPlayer.media.duration.toMillis() > 0 and
        mediaPlayer.currentTime.toMillis() > 0)
    {
        time_control_length * mediaPlayer.currentTime.toMillis() / mediaPlayer.media.duration.toMillis()
    } else {
        0.0
    };
var bufferedTime = bind
    if (mediaPlayer.media != null and
        mediaPlayer.media.duration != null and
        mediaPlayer.media.duration.toMillis() > 0 and
        mediaPlayer.bufferProgressTime.toMillis() > 0)
    {
        time_control_length * mediaPlayer.bufferProgressTime.toMillis() / mediaPlayer.media.duration.toMillis()
    } else {
        0.0
    };
var time_control:ImageView = ImageView { id: "time_control"
    cursor: Cursor.HAND
    opacity: 1.0 visible: true
    x: bind currentTime + time_control_xoff  y: 143
    image: Image { url: "{__DIR__}images/MP3_handoff_time_control.png" },
    blocksMouse: true
    onMouseDragged: function(e) {
        if (mediaPlayer.media != null and mediaPlayer.media.duration > 0s) {
            var x = e.x;
            var available = mediaPlayer.bufferProgressTime.toMillis() / mediaPlayer.media.duration.toMillis();
            var xmin = time_control_xoff;
            var xmax = xmin + (available*time_control_length);
            if (x > xmin and x < xmax) {
                var t = (x - xmin) / time_control_length * mediaPlayer.media.duration.toMillis();
                mediaPlayer.currentTime = Duration.valueOf(t);
            }
        }
    }
};

var current_time_indicator = ImageView { id: "current_time_indicator"
    opacity: 1.0 visible: true
    translateX: 214
    translateY: 154
    image: Image { url: "{__DIR__}images/MP3_handoff_blue_play_fill.png" }
    clip: Rectangle { x: 0 y: 0 width: bind currentTime height: 20}
};

var buffering_indicator = Rectangle {
    fill: LinearGradient {
        startX: 0 startY: 0
        endX: 1 endY: 0
        stops: [
            Stop { offset: 0.9 color: Color.rgb(255, 255, 255, 0.1) }
            Stop { offset: 1.0 color: Color.TRANSPARENT }
        ]
    }
    translateX: 216
    translateY: 157
    width: bind bufferedTime
    height: 2
};

function getTimeString(dur:Duration):String {
    if (dur == null or dur < 0s) {
        return "0:00";
    } else {
        var minutes = dur.toMinutes() as Integer;
        var seconds = dur.toSeconds() mod 60 as Integer;
        return "{minutes}:{%02d seconds}";
    }
}

var current_time = Text {
    fill: Color.web("#0d9c0d")
    x: 465 y: 160 font: Font { size: 9 }
    content: bind getTimeString(mediaPlayer.currentTime)
};
var total_time = Text {
    fill: Color.web("#c5c5c5")
    x: 490 y: 160 font: Font { size: 9 }
    content: bind "/ {getTimeString(mediaPlayer.media.duration)}"
};



    
var volume_icon = ImageView {
    id: "volume_icon"
    opacity: 1.0
    x: 542
    y: 150
    image: Image {
        url: "{__DIR__}images/MP3_handoff_volume_icon.png"
    },
};

var volume_group:Group = Group {
    translateY: 110
    content: [
        ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_bkg.png" } 
            blocksMouse: true
            onMouseDragged:function(e) {
                var v = (e.y-14)/65;
                if(v < 0) { v = 0; }
                if(v > 1.0) { v = 1.0; }
                v = 1-v;
                mediaPlayer.volume = v;
            }
        },
        Rectangle { x: 22 y: 16 width: 12 height: 68 
            fill: bind LinearGradient {
                    startX:0 endX: 0 startY: 0 endY: 1 proportional: true
                    stops: [
                        Stop { color: Color.BLACK offset: 0.0 },
                        Stop { color: Color.GREEN offset: 0.99-(mediaPlayer.volume*0.98) },
                        Stop { color: Color.GREEN offset: 1.0 },
                    ]
                }
            },
        ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_outline_inner_shadow.png" } x: 21 y: 15},
        ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_slider.png" } 
            x: 13
            y: bind (1-mediaPlayer.volume) * 65 + 14
        },
    ]
};
var volume_group_wrapper = Group { 
    blocksMouse: true
    translateX: 523
    translateY: 30
    content: volume_group
    clip: Rectangle { width: 100 height: 130 }
};

var reveal_volume = Timeline {
    keyFrames: [ 
        at (0s)   { volume_group.translateY => 110 },
        at (0.3s) { volume_group.translateY => 0 },
    ]
}

var volume_rollover = ImageView {
    id: "volume_rollover"
    opacity: 0.0
    x: 542
    y: 150
    blocksMouse: true
    image: Image {
        url: "{__DIR__}images/MP3_handoff_volume_rollover.png"
    },
    effect: Glow { }
    onMousePressed: function(e) {
        reveal_volume.rate *= -1.0;
        reveal_volume.play();
    }
};
RolloverBehavior { target: volume_rollover };

function createGradient(color:Color) {
    return LinearGradient {
        proportional: false
        startX: 0 startY: 0 endX: 275 endY: 0
        stops: [
            Stop { offset: 0.0 color: color }
            Stop { offset: 0.8 color: color }
            Stop { offset: 1.0 color: Color.TRANSPARENT }
        ]
    }
}

var songInfo = Group {
    translateX: 300
    translateY: 100
    content: [
        Text {
            content: bind "{playlist.songs[playlist.currentSong].name}"
            x: 0 y: 0 fill: createGradient(Color.WHITE);
        }
        Text {
            content: bind "{playlist.songs[playlist.currentSong].artist}"
                       " - {playlist.songs[playlist.currentSong].album}"
            x: 0 y: 18 fill: createGradient(Color.color(0.7, 0.7, 0.7));
        }
    ]
};



stage = Stage {
    title: "MP3 Player"
    visible: true
    width: 510
    height: 345
    style:StageStyle.TRANSPARENT
    scene: Scene {
        fill: bind if (inBrowser) Color.WHITE else Color.TRANSPARENT
        content: Group {
            translateX: -75
            translateY: -25
            content: [
                can_drag_me,
    
                playlist_group,
    
                // the player itself
                player_normal,

                // the rollovers
                fx_rollover,
                playlist_rollover,
                playBack,
                playForward,
                stop,
                play_rollover,

                // the time control and labels
                buffering_indicator,
                current_time_indicator,
                time_control,
                current_time,
                total_time,

                // drag controls
                dragRect,
                can_drag_me_text,
                drag_closers,

                //volume control,
                volume_group_wrapper,
                ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_volume_bkg.png" } x: 491 y: 130 },
                volume_icon,
                volume_rollover,

                // text on the player itself
                songInfo,

                // the song info popup
                song_info_popup,
            ]
        }
    }
    extensions: [
        AppletStageExtension {
            shouldDragStart: function(e): Boolean {
                return inBrowser and e.primaryButtonDown and dragRect.hover;
            }
            onDragStarted: function(): Void {
                inBrowser = false;
            }
            onAppletRestored: function(): Void {
                inBrowser = true;
            }
            useDefaultClose: false
        }
    ]
}