#include "untrashjob.h"

namespace Fm {

UntrashJob::UntrashJob() {

}

static const char trash_query[] =
    G_FILE_ATTRIBUTE_STANDARD_TYPE","
    G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
    G_FILE_ATTRIBUTE_STANDARD_NAME","
    G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL","
    G_FILE_ATTRIBUTE_STANDARD_SIZE","
    G_FILE_ATTRIBUTE_UNIX_BLOCKS","
    G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE","
    G_FILE_ATTRIBUTE_ID_FILESYSTEM","
    "trash::orig-path";

bool UntrashJob::ensure_parent_dir(GFile* orig_path) {
    GFile* parent = g_file_get_parent(orig_path);
    gboolean ret = g_file_query_exists(parent, cancellable().get());
    if(!ret) {
        GErrorPtr err;
_retry_mkdir:
        if(!g_file_make_directory_with_parents(parent, cancellable().get(), &err)) {
            if(!isCancelled()) {
                ErrorAction act = emitError(err, ErrorSeverity::MODERATE);
                err = nullptr;
                if(act == ErrorAction::RETRY) {
                    goto _retry_mkdir;
                }
            }
        }
        else {
            ret = TRUE;
        }
    }
    g_object_unref(parent);
    return ret;
}


void UntrashJob::exec() {
#if 0
    gboolean ret = TRUE;
    GList* l;
    GError* err = nullptr;
    FmJob* fmjob = FM_JOB(job);
    job->total = fm_path_list_get_length(job->srcs);
    fm_file_ops_job_emit_prepared(job);

    l = fm_path_list_peek_head_link(job->srcs);
    for(; !fm_job_is_cancelled(fmjob) && l; l = l->next) {
        GFile* gf;
        GFileInfo* inf;
        FmPath* path = FM_PATH(l->data);
        if(!fm_path_is_trash(path)) {
            continue;
        }
        gf = fm_path_to_gfile(path);
_retry_get_orig_path:
        inf = g_file_query_info(gf, trash_query, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, fm_job_get_cancellable(fmjob), &err);
        if(inf) {
            const char* orig_path_str = g_file_info_get_attribute_byte_string(inf, "trash::orig-path");
            fm_file_ops_job_emit_cur_file(job, g_file_info_get_display_name(inf));

            if(orig_path_str) {
                /* FIXME: what if orig_path_str is a relative path?
                 * This is actually allowed by the horrible trash spec. */
                GFile* orig_path = fm_file_new_for_commandline_arg(orig_path_str);
                FmFolder* src_folder = fm_folder_find_by_path(fm_path_get_parent(path));
                FmPath* orig_fm_path = fm_path_new_for_gfile(orig_path);
                FmFolder* dst_folder = fm_folder_find_by_path(fm_path_get_parent(orig_fm_path));
                fm_path_unref(orig_fm_path);
                /* ensure the existence of parent folder. */
                if(ensure_parent_dir(fmjob, orig_path)) {
                    ret = _fm_file_ops_job_move_file(job, gf, inf, orig_path, path, src_folder, dst_folder);
                }
                if(src_folder) {
                    g_object_unref(src_folder);
                }
                if(dst_folder) {
                    g_object_unref(dst_folder);
                }
                g_object_unref(orig_path);
            }
            else {
                ErrorAction act;

                g_set_error(&err, G_IO_ERROR, G_IO_ERROR_FAILED,
                            _("Cannot untrash file '%s': original path not known"),
                            g_file_info_get_display_name(inf));
                act = emitError( err, ErrorSeverity::MODERATE);
                g_clear_error(&err);
                if(act == ErrorAction::ABORT) {
                    g_object_unref(inf);
                    g_object_unref(gf);
                    return FALSE;
                }
            }
            g_object_unref(inf);
        }
        else {
            char* basename = g_file_get_basename(gf);
            char* disp = basename ? g_filename_display_name(basename) : nullptr;
            g_free(basename);
            /* FIXME: translate it */
            fm_file_ops_job_emit_cur_file(job, disp ? disp : "(invalid file)");
            g_free(disp);

            if(err) {
                ErrorAction act = emitError( err, ErrorSeverity::MODERATE);
                g_error_free(err);
                err = nullptr;
                if(act == ErrorAction::RETRY) {
                    goto _retry_get_orig_path;
                }
                else if(act == ErrorAction::ABORT) {
                    g_object_unref(gf);
                    return FALSE;
                }
            }
        }
        g_object_unref(gf);
        ++job->finished;
        fm_file_ops_job_emit_percent(job);
    }
#endif
}

} // namespace Fm
