/*
Theme Name: Melawy
Version: 1.0
Description: My theme
Author: Valeria Fadeeva - https://github.com/Valeria-Fadeeva
Date: 2023.04.04
License: GNU AFFERO GENERAL PUBLIC LICENSE, see <http://www.gnu.org/licenses/>
*/

Window.GetMaxWidth = function() {
    i = 0;
    width = 0;
    while (Window.GetWidth(i)){
        width = Math.Max(width, Window.GetWidth(i));
        i++;
    }
    return width;
};

Window.GetMaxHeight = function() {
    i = 0;
    height = 0;
    while (Window.GetHeight(i)){
        height = Math.Max(height, Window.GetHeight(i));
        i++;
    }
    return height;
};

Percent = function(perc, pixels) {
    result = Math.Int(Math.Abs(Math.Int(pixels)) / 100 * Math.Abs(Math.Int(perc)));
    return result;
};

Limit = function(width, height, perc) {
    local.this;
    this.width = width;
    this.height = height;
    this.perc = perc;

    this.GetWidth = function() {
        width = Percent(this.perc, this.width);
        return width;
    };

    this.GetHeight = function() {
        height = Percent(this.perc, this.height);
        return height;
    };

    return this;
};

ScaleImage = function(image1, image2) {
    img1.width = image1.GetWidth();
    img1.height = image1.GetHeight();
    img1.ratio = img1.width / img1.height;

    img2.width = image2.GetWidth();
    img2.height = image2.GetHeight();
    img2.ratio = img2.width / img2.height;

    if (img1.ratio == 1 || (img1.width < 200 && img1.height < 200)) {
        img1.scaled = image1.Scale(img2.width, img2.height);
        return img1.scaled;
    }

    if (img1.width == img2.width && img1.height == img2.height) {
        return image1;
    }

    if (img2.ratio < img1.ratio) {
        factor = img2.height / img1.height;
    } else {
        factor = img2.width / img1.width;
    }

    img1.scaled = image1.Scale(img1.width * factor, img1.height * factor);

    return img1.scaled;
};

FitIntoDimensions = function(image1, image2) {
    img1.width = image1.GetWidth();
    img1.height = image1.GetHeight();

    img2.width = image2.GetWidth();
    img2.height = image2.GetHeight();

    ma = Math.Max(img1.width, img2.height);
    mi = Math.Min(img1.height, img2.height);
    factor = ma / mi;

    img1.fit = image1.Scale(Math.Int(img1.width / factor), Math.Int(img1.height / factor));

};

SetSpriteImage = function(asset, x, y, z) {
    local.sprite = Sprite();
    sprite.image = Image(asset);
    sprite.width = sprite.image.GetWidth();
    sprite.height = sprite.image.GetHeight();
    sprite.SetImage(sprite.image);
    sprite.SetPosition(x, y, z);
    return sprite;
};


// TEXT
common_font = "Noto Sans Mono Regular 10";
progressfont = "Noto Sans Mono Regular 12";
link_font = "Noto Sans Italic 16";

starting_text = "Starting up...";
bye_text = "System is shutting down";
progress_t= 0;

x0 = Window.GetX();
y0 = Window.GetY();
z0 = Window.GetZ();

Window.SetBackgroundTopColor(0, 0, 0);
Window.SetBackgroundBottomColor(0, 0, 0);

screen.width = Window.GetMaxWidth();
screen.height = Window.GetMaxHeight();

// BACKGROUND
background.image = Image("BACKGROUND.png");
background.image = ScaleImage(background.image, Limit(screen.width, screen.height, 100));

background.width = background.image.GetWidth();
background.height = background.image.GetHeight();

background.x = x0 + screen.width / 2 - background.width / 2;
background.y = y0 + screen.height / 2 - background.height / 2;

//background.x = x0;
//background.y = y0;

background.sprite = SpriteNew();
background.sprite.SetImage(background.image);
background.sprite.SetPosition(background.x, background.y, 0);
background.sprite.SetOpacity(1);

// SIDE BACKGROUND
side_panel.image = Image("SIDE_BACKGROUND2.png");
side_panel.image = side_panel.image.Scale(Percent(25, screen.width), Percent(100, screen.height));

side_panel.width = side_panel.image.GetWidth();
side_panel.height = side_panel.image.GetHeight();

side_panel.x = x0;
side_panel.y = y0;

side_panel.sprite = Sprite(side_panel.image);
side_panel.sprite.SetPosition(side_panel.x, side_panel.y, 1);
side_panel.sprite.SetOpacity(0.75);

// MESSAGES BOX
messages_box.image = Image("MESSAGES_BOX.png");
messages_box.image = messages_box.image.Scale(Percent(80, side_panel.width), Percent(40, side_panel.height));

messages_box.width = messages_box.image.GetWidth();
messages_box.height = messages_box.image.GetHeight();

messages_box.x = Percent(50, side_panel.width) - messages_box.width / 2;
messages_box.y = Percent(45, side_panel.height) - messages_box.height;

messages_box.sprite = Sprite(messages_box.image);
messages_box.sprite.SetPosition(messages_box.x, messages_box.y, 2);
messages_box.sprite.SetOpacity(1);

// Sise Logo
side_logo.image = Image("Melawy_Linux_640x320.png");
side_logo.image = ScaleImage(side_logo.image, Limit(screen.width, screen.height, 20));

side_logo.width = side_logo.image.GetWidth();
side_logo.height = side_logo.image.GetHeight();

side_logo.x = (side_panel.width - side_logo.width) / 2;
side_logo.y = side_panel.height - side_panel.height * 0.25;

side_logo.sprite = Sprite(side_logo.image);
side_logo.sprite.SetPosition(side_logo.x, side_logo.y, 2);
side_logo.sprite.SetOpacity(1);

// **************************************** //

project_link.image = Image.Text("https://Melawy.ru", 0.5, 0.5, 0.5, 1, link_font);

project_link.width = project_link.image.GetWidth();
project_link.height = project_link.image.GetHeight();

project_link.sprite = Sprite(project_link.image);
project_link.x = (side_panel.width - project_link.width) / 2;
project_link.y = side_logo.y + side_logo.height;

project_link.sprite.SetPosition(project_link.x, project_link.y, 2);
project_link.sprite.SetOpacity(1);

// **************************************** //

// LOGO
logo.image = Image("MAIN_LOGO.png");
logo.image = FitIntoDimensions(logo.image, Limit(screen.width, screen.height, 35));

logo.sprite = Sprite(logo.image);
logo.x = screen.width / 2  -  logo.image.GetWidth() / 2;             // позиция логотипа X
logo.y = Percent(10, screen.height);         // позиция логотипа Y
logo.sprite.SetPosition(logo.x, logo.y, 2);
logo.sprite.SetOpacity(1);

// PROGRESS FORM
progress_form.image = Image("PROGRESS_FORM.png");
progress_form.image = progress_form.image.Scale(Percent(80, side_panel.width), Percent(10, side_panel.height));

progress_form.width = progress_form.image.GetWidth();
progress_form.height = progress_form.image.GetHeight();

progress_form.x = Percent(50, side_panel.width) - progress_form.width / 2;
progress_form.y = Percent(75, side_panel.height) - progress_form.height;

progress_form.sprite = Sprite(progress_form.image);
progress_form.sprite.SetPosition(progress_form.x, progress_form.y, 2);
progress_form.sprite.SetOpacity(1);

// SPINNER
spinner.image = Image("SPINNER.png");
spinner.image = spinner.image.Scale(Percent(1, screen.width), Percent(1, screen.width));

spinner.width = spinner.image.GetWidth();
spinner.height = spinner.image.GetHeight();

spinner.x = progress_form.x + progress_form.width - Percent(10, progress_form.width);
spinner.y = progress_form.y + Percent(10, progress_form.height);

spinner.sprite = Sprite(spinner.image);
spinner.sprite.SetPosition(spinner.x, spinner.y, 3); // позиция за или перед


// PROGRESS TEXT
progress_text.image = Image.Text(progress_t + "%", 0.5, 0.5, 0.5, 1, progressfont);

progress_text.width = progress_text.image.GetWidth();
progress_text.height = progress_text.image.GetHeight();

progress_text.x = progress_form.x + Percent(5, progress_form.width); // позиция % по X
progress_text.y = progress_form.y + Percent(10, progress_form.height); // позиция % по Y

progress_text.sprite = SpriteNew();
progress_text.sprite.SetPosition(progress_text.x, progress_text.y, 3);

// PROGRESS BOX
progress_box.image = Image("PROGRESS_BOX.png");
progress_box.image = progress_box.image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height));

progress_box.width = progress_box.image.GetWidth();
progress_box.height = progress_box.image.GetHeight();

progress_box.x = progress_form.x + (progress_form.width - progress_box.width) / 2;
progress_box.y = progress_form.y + (progress_form.height - progress_box.height) / 2;

progress_box.sprite = Sprite(progress_box.image);
progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 3);

// PROGRESS BAR
progress_bar.original_image = Image("PROGRESS_BAR.png");
progress_bar.original_image = progress_bar.original_image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height));

progress_bar.width = progress_bar.original_image.GetWidth();
progress_bar.height = progress_bar.original_image.GetHeight();

progress_bar.x = progress_form.x + (progress_form.width - progress_bar.original_image.GetWidth()) / 2;
progress_bar.y = progress_form.y + (progress_form.height - progress_bar.original_image.GetHeight()) / 2;

progress_bar.sprite = Sprite();
progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 4);

// PROGRESS FADE
progress_fade.image = Image("PROGRESS_FADE.png");
progress_fade.image = progress_fade.image.Scale(Percent(10, progress_form.width), Percent(15, progress_form.height));

progress_fade.width = progress_fade.image.GetWidth();
progress_fade.height = progress_fade.image.GetHeight();

progress_fade.sprite = Sprite(progress_fade.image);

fade_dir = 0; // 0 = right, 1 = left
counter = 0;
max_counter = progress_box.width - progress_fade.width;



function progress_callback(duration, progress) {
    if (progress_bar.image.GetWidth() != Math.Int(progress_bar.original_image.GetWidth() * progress)) {
        progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress, progress_bar.original_image.GetHeight());
        progress_bar.sprite.SetImage(progress_bar.image);

        f = Math.Int(progress_bar.image.GetWidth() /progress_bar.original_image.GetWidth() * 100);
        progress_t.image = Image.Text(f + "%", 0.5, 0.5, 0.5, 1, progressfont);
        progress_text.sprite.SetImage(progress_t.image);
    }
}

Plymouth.SetBootProgressFunction(progress_callback);



// DIALOG
status = "normal";
//count = 0;

function dialog_setup() {
    local.box_form;
    local.lock;
    local.entry;
    local.hint;
    local.bullet_i;

    box_form.image = Image("BOX.png");
    box_form.image = box_form.image.Scale(Percent(80, side_panel.width), Percent(10, side_panel.height));

    box_form.width = box_form.image.GetWidth();
    box_form.height = box_form.image.GetHeight();

    box_form.x = progress_form.x;
    box_form.y = progress_form.y - box_form.height - Percent(1, side_panel.height);
    box_form.z = 10000;

    box_form.sprite = Sprite(box_form.image);
    box_form.sprite.SetPosition(box_form.x, box_form.y, box_form.z);
    box_form.sprite.SetOpacity(1);


    entry.image = Image("ENTRY.png");
    entry.image = entry.image.Scale(Percent(90, box_form.width), Percent(33, box_form.height));
    entry.width = entry.image.GetWidth();
    entry.height = entry.image.GetHeight();

    entry.x = box_form.x + box_form.width/2 - entry.width/2;
    entry.y = box_form.y + box_form.height/2 - entry.height/2;
    entry.z = box_form.z + 1;

    entry.sprite = Sprite(entry.image);
    entry.sprite.SetPosition(entry.x, entry.y, entry.z);


    lock.image = Image("LOCK.png");
    lock.image = lock.image.Scale(Percent(95, entry.height), Percent(95, entry.height));
    lock.width = lock.image.GetWidth();
    lock.height = lock.image.GetHeight();

    lock.x = entry.x + entry.width - lock.width - (entry.height - lock.height);
    lock.y = entry.y + entry.height/2 - lock.height/2;
    lock.z = box_form.z + 2;

    lock.sprite = Sprite(lock.image);
    lock.sprite.SetPosition(lock.x, lock.y, lock.z);


    hint.sprite = SpriteNew();
    hint.sprite.SetPosition(entry.x, box_form.y + Percent(5, box_form.height), box_form.z + 1);


    bullet_i.image = Image("BULLET.png");
    bullet_i.image = bullet_i.image.Scale(Percent(50, entry.height), Percent(50, entry.height));
    bullet_i.width = bullet_i.image.GetWidth();
    bullet_i.height = bullet_i.image.GetHeight();


    global.dialog.box_form = box_form;
    global.dialog.lock = lock;
    global.dialog.entry = entry;
    global.dialog.hint = hint;
    global.dialog.bullet_i = bullet_i;
    dialog_opacity(1);
}

function dialog_opacity(opacity) {
    if (opacity == 0) {
        dialog.box_form.sprite.SetOpacity(opacity);
        dialog.lock.sprite.SetOpacity(opacity);
        dialog.entry.sprite.SetOpacity(opacity);
    }
    else {
        dialog.lock.sprite.SetOpacity(opacity);
        dialog.entry.sprite.SetOpacity(opacity);
    }

    dialog.hint.sprite.SetOpacity(opacity);

    for (index = 0; dialog.bullet[index]; index++) {
        dialog.bullet[index].sprite.SetOpacity(opacity);
    }
}


function display_normal_callback() {
    global.status = "normal";

    if (global.dialog)
        dialog_opacity(0);
}

Plymouth.SetDisplayNormalFunction(display_normal_callback);



function display_password_callback(prompt_text, bullets) {
    global.status = "password";

    if (!global.dialog)
        dialog_setup();
    else
        dialog_opacity(1);

    dialog.hint.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font);
    dialog.hint.sprite.SetImage(dialog.hint.image);

    for (index = 0; dialog.bullet[index] || index < bullets; index++) {
        if (!dialog.bullet[index]) {
            dialog.bullet[index].sprite = Sprite(dialog.bullet_i.image);
            dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_i.width / 0.9 - dialog.entry.height * -0.2; // отступ точки от точки и от поля(modified)
            dialog.bullet[index].y = dialog.entry.y + (dialog.entry.height - dialog.bullet_i.height) / 2;
            dialog.bullet[index].z = dialog.entry.z + 1;
            dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z);
        }
        if (index < bullets)
            dialog.bullet[index].sprite.SetOpacity(1);
        else
            dialog.bullet[index].sprite.SetOpacity(0);
    }
}

Plymouth.SetDisplayPasswordFunction(display_password_callback);



time = 1;

function refreshHandler() {
    if (global.status == "normal" &&  Plymouth.GetMode() == "boot") {
        progress_fade.sprite.SetOpacity (0); // полностью прозрачный
        progress_bar.sprite.SetOpacity (1);
        text.image = Image.Text(starting_text, 0.5, 0.5, 0.5, 1, common_font);
        text.sprite = Sprite(text.image);
        text.x = progress_box.x;
        text.y = progress_box.y - progress_text.image.GetHeight() * 2;
        text.sprite.SetPosition(text.x, text.y, 3);
    }
    else {
        progress_fade.sprite.SetOpacity (1);
        progress_bar.sprite.SetOpacity (0);
        text_end.image = Image.Text(bye_text, 0.5, 0.5, 0.5, 1, common_font);
        text_end.sprite = Sprite(text_end.image);
        text_end.x = progress_box.x;
        text_end.y = progress_box.y - progress_text.image.GetHeight() * 2;
        text_end.sprite.SetPosition(text_end.x, text_end.y, 3);
    }

    progress_fade.x = progress_bar.x;
    progress_fade.y = progress_bar.y;
    progress_fade.sprite.SetPosition(counter + progress_fade.x, progress_fade.y, 4);

    if (fade_dir == 0) {
        counter++;
        if (counter >= max_counter) {
            fade_dir = 1;
        }
    }
    else {
        counter--;
        if (counter <= 0) {
            fade_dir = 0;
        }
    }

    /* if fsck is running or the password is prompted, hide the spinner */
    if (fsck_running == 1 || passw_dialog_input_sprite.GetOpacity() == 1) {
        spinner.sprite.SetOpacity(0);
    }
    else {
        spinner.sprite.SetOpacity(1);
        time++;
        theta = time / (Math.Pi * 2);
        spinner.sprite.SetImage(spinner.image.Rotate(theta));
    }

    if ((fsck_running == 1) && (fsck_done_fading == 0)) {
        fsck_progress_meter_sprite.SetOpacity(fsck_fade_in_counter);
        fsck_progress_fade_sprite.SetOpacity(fsck_fade_in_counter);

        if (fsck_fade_in_counter < 1) {
            fsck_fade_in_counter+= 0.025;
        }
        else {
            fsck_done_fading = 1;
        }
    }
}

Plymouth.SetRefreshFunction(refreshHandler);



message_status.sprite = SpriteNew();

function message_callback(prompt_text) {
    message_status.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font);
    message_status.sprite.SetImage(message_status.image);
    message_status.height = message_status.image.GetHeight();
    message_status.x = messages_box.x + Percent(5, messages_box.width);
    message_status.y = messages_box.y + messages_box.height - Percent(7, messages_box.height);
    message_status.sprite.SetPosition(message_status.x, message_status.y, 3);
    message_status.sprite.SetOpacity(1);
}

Plymouth.SetMessageFunction(message_callback);

// высота messages_box = screen.height - 40% (1080 * 0,4 = 432)
// высота всех сообщений = NUM_SCROLL_LINES (20) * (LINE_HEIGHT) 17 = 340
// 10 процентов сверху от начала messages_box.x = 432 - 10% (432 * 0,1) = 432 - 43 = 389
// конечная точка, где допустимо показывать сообщения = 389 - 43 (10% от высоты messages_box.x) = 346
// если высота всех сообщений выше, чем высота (messages_box.height - 20%), то уменьшать количество строк, пока высота всех сообщений не быдет меньше (messages_box.height - 20%)

padding_top_bottom = Percent(10, messages_box.height);
padding_left_right = Percent(5, messages_box.width);

message_sprite_.x = messages_box.x + (padding_left_right); // позиция % по X (слева направо)
message_sprite_.y = messages_box.y + (padding_top_bottom); // позиция % по Y (сверху вниз)

// LOG //
NUM_SCROLL_LINES=20; //количество строк лога
LINE_WIDTH=40; //ширина строк лога
LINE_HEIGHT=17;

for (index = NUM_SCROLL_LINES; index > 0; index--) {
    if ((NUM_SCROLL_LINES * LINE_HEIGHT) > (messages_box.height - (padding_top_bottom * 2))) {
        NUM_SCROLL_LINES=NUM_SCROLL_LINES-1;
    }
    else {
        break;
    }
}

// Initialising text images and their positions
// 20 is the height(including line spacing) of each line
for (i=0; i < NUM_SCROLL_LINES; i++) {
    lines[i]= Image.Text("", 0.5, 0.5, 0.5, 1, common_font); //цвет строк
    message_sprite[i] = SpriteNew();
    message_sprite[i].SetPosition(message_sprite_.x, message_sprite_.y + (i * LINE_HEIGHT), 3);
}                                    //высота строк           //отступ строк

function StringLength(string) {
    index = 0;
    str = String(string);
    while(str.CharAt(index)) index++;
    return index;
}

function scroll_message_callback(text) {
    //  Truncate the message if too long
    if (StringLength(text) > LINE_WIDTH) {
        text = text.SubString(0, LINE_WIDTH - 3);
        text += "...";
    }

    //  Shift message one up
    for (i = 0; i < NUM_SCROLL_LINES - 1; i++) {
        lines[i] = lines[i+1];
    }

    //  Create the image for the latest message
    lines[i] = Image.Text(text, 0.5, 0.5, 0.5, 1, common_font);

    //  Re-positioning the text images
    for (i = 0; i < NUM_SCROLL_LINES; i++) {
        message_sprite[i].SetImage(lines[i]);
    }
}

Plymouth.SetUpdateStatusFunction(scroll_message_callback);



// QUIT
function quit_callback() {
    progress_fade.sprite.SetOpacity (1);
    progress_bar.sprite.SetOpacity (0);
    if (Plymouth.GetMode() == "shutdown") {
        logo.sprite.SetOpacity(0);
    }
}

Plymouth.SetQuitFunction(quit_callback);