{
    UninstallProcessWindow используется для создания окна, в котором пользователь
    наблюдает процесс удаления программы с Малик Эмулятора и ошибки,
    которые могли возникнуть в процессе удаления.
    Этот исходный текст является частью Малик Эмулятора.

    Следующие файлы используются этим исходным текстом:
        uninstallprocesswindow.lfm
    На них так же распространяются те же права, как и на этот исходный текст.

    Copyright © 2016–2017, 2019–2022 Малик Разработчик

    Малик Эмулятор – свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Малик Эмулятор распространяется в надежде, что он может быть полезен,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
}

unit UninstallProcessWindow;

{$MODE DELPHI}

interface

uses
    Classes,
    SysUtils,
    Forms,
    StdCtrls,
    ExtCtrls,
    LMessages,
    LCLIntf,
    Lang,
    IOStreams,
    FileIO,
    Manifests,
    EmulConstants,
    EmulProgrammes,
    EmulatorInterfaces;

{%region public }
type
    TUninstallProcessForm = class(TForm, _Interface, Runnable)
        dialogError: TImage;
        dialogInformation: TImage;
        uninstallResult: TMemo;
        uninstallButton: TButton;
        cancelButton: TButton;
        procedure formClose(sender: TObject; var action: TCloseAction);
        procedure uninstallButtonClick(sender: TObject);
    private
        owner: MainWindowInterface;
        uninstalled: boolean;
        uninstallID: AnsiString;
        uninstallMessage: AnsiString;
        directory: AnsiString;
        emulatorDirectory: AnsiString;
    protected
        message: AnsiString;
        procedure lmUninstallEnd(var theMessage: TLMessage); message LM_USER + 1;
        procedure lmUninstallError(var theMessage: TLMessage); message LM_USER + 2;
    public
        constructor create(theOwner: TComponent); override;
        { _Interface }
        function getClass(): _Class;
        function asObject(): TObject;
        { Runnable }
        procedure run();
        { Собственные методы }
        procedure setUninstallID(const uninstallID: AnsiString);
        function isUninstalled(): boolean;
    end;
{%endregion}

implementation

{$R *.LFM}

{%region TUninstallProcessForm }
    constructor TUninstallProcessForm.create(theOwner: TComponent);
    begin
        inherited create(theOwner);
        theOwner.getInterface(stringToGUID(MAIN_WINDOW_INTERFACE_GUID), owner);
        uninstalled := false;
        emulatorDirectory := getEmulatorDirectory();
    end;

    procedure TUninstallProcessForm.formClose(sender: TObject; var action: TCloseAction);
    begin
        if cancelButton.enabled then begin
            action := caHide;
        end else begin
            action := caNone;
        end;
    end;

    procedure TUninstallProcessForm.uninstallButtonClick(sender: TObject);
    begin
        uninstallResult.lines.add('Выполняется удаление программы…');
        uninstallResult.setFocus();
        uninstallButton.enabled := false;
        cancelButton.enabled := false;
        startThread(self);
    end;

    procedure TUninstallProcessForm.lmUninstallEnd(var theMessage: TLMessage);
    begin
        uninstallResult.text := message;
        cancelButton.enabled := true;
        cancelButton.caption := 'Закрыть';
    end;

    procedure TUninstallProcessForm.lmUninstallError(var theMessage: TLMessage);
    begin
        dialogInformation.visible := false;
        dialogError.visible := true;
        uninstallResult.text := message;
        cancelButton.enabled := true;
        cancelButton.caption := 'Закрыть';
    end;

    function TUninstallProcessForm.getClass(): _Class;
    begin
        result := ClassData.create(classType());
    end;

    function TUninstallProcessForm.asObject(): TObject;
    begin
        result := self;
    end;

    procedure TUninstallProcessForm.run();
    var
        msg: AnsiString;
    begin
        uninstalled := true;
        try
            if not destroyDirectory(directory, true) then begin
                raise IOException.create('Не удалось полностью удалить папку программы ' + directory);
            end;
            message := 'Программа была удалена с Малик Эмулятора.';
            msg := uninstallMessage;
            if msg <> '' then begin
                message := message + (LINE_ENDING + LINE_ENDING + 'Сообщение от разработчиков удалённой программы:' + LINE_ENDING) + msg;
            end;
            postMessage(handle, LM_USER + 1, 0, 0);
        except
            on e: SysUtils.Exception do begin
                message := (
                    'Во время удаления программы возникла ошибка.' + LINE_ENDING +
                    'Класс: ') + (e.unitName() + '.' + e.className()) + (LINE_ENDING +
                    'Сообщение: ') + e.message
                ;
                postMessage(handle, LM_USER + 2, 0, 0);
            end;
            on e: Lang.Exception do begin
                message := (
                    'Во время удаления программы возникла ошибка.' + LINE_ENDING +
                    'Класс: ') + e.getClass().getName() + (LINE_ENDING +
                    'Сообщение: ') + e.getMessage()
                ;
                postMessage(handle, LM_USER + 2, 0, 0);
            end;
        end;
    end;

    procedure TUninstallProcessForm.setUninstallID(const uninstallID: AnsiString);
    var
        info: ProgrammeInfo;
        pman: ProgrammeManifest;
        directory: AnsiString;
        programme: AnsiString;
        message: AnsiString;
        msg: AnsiString;
    begin
        directory := trim(owner.getSetting(SECTION_PROGRAMMES, uninstallID, ''));
        if (length(directory) < 2) or (not (directory[1] in ['A'..'Z', 'a'..'z'])) or (directory[2] <> ':') then begin
            directory := emulatorDirectory + directory;
        end;
        self.uninstallID := uninstallID;
        self.directory := directory;
        info := ProgrammeInfo.create(directory + DIRECTORY_SEPARATOR);
        try
            pman := ProgrammeManifest.create();
            try
                info.loadManifest(pman);
                programme := trim(pman.getValue(MANIFEST_PROPERTY_PROGRAMME_NAME));
                msg := trim(pman.getValue(MANIFEST_PROPERTY_PROGRAMME_DELETE_CONFIRM));
                uninstallMessage := trim(pman.getValue(MANIFEST_PROPERTY_PROGRAMME_DELETE_NOTIFY));
            finally
                pman.free();
            end;
        finally
            info.free();
        end;
        message := 'Вы собираетесь удалить программу ' + programme + ('.' + LINE_ENDING + 'ОСТОРОЖНО: все сохранённые этой программой данные так же будут удалены.' + LINE_ENDING);
        if msg <> '' then begin
            message := message + (LINE_ENDING + 'Сообщение от разработчиков удаляемой программы:' + LINE_ENDING) + msg + (LINE_ENDING + LINE_ENDING);
        end;
        message := message + 'Чтобы начать процесс удаления, нажмите кнопку «Удалить».';
        uninstallResult.text := message;
    end;

    function TUninstallProcessForm.isUninstalled(): boolean;
    begin
        result := uninstalled;
    end;
{%endregion}

end.

