/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui;

import android.os.AsyncTask;

import androidx.annotation.GuardedBy;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;

public class ProviderExecutor extends Thread implements Executor {

    @GuardedBy("sExecutors")
    private static HashMap<String, ProviderExecutor> sExecutors = new HashMap<>();

    public static ProviderExecutor forAuthority(String authority) {
        synchronized (sExecutors) {
            ProviderExecutor executor = sExecutors.get(authority);
            if (executor == null) {
                executor = new ProviderExecutor();
                executor.setName("ProviderExecutor: " + authority);
                executor.start();
                sExecutors.put(authority, executor);
            }
            return executor;
        }
    }

    public interface Preemptable {
        void preempt();
    }

    private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();

    private final ArrayList<WeakReference<Preemptable>> mPreemptable = new ArrayList<>();

    private void preempt() {
        synchronized (mPreemptable) {
            int count = 0;
            for (WeakReference<Preemptable> ref : mPreemptable) {
                final Preemptable p = ref.get();
                if (p != null) {
                    count++;
                    p.preempt();
                }
            }
            mPreemptable.clear();
        }
    }

    /**
     * Execute the given task. If given task is not {@link Preemptable}, it will
     * preempt all outstanding preemptable tasks.
     */
    public <P> void execute(AsyncTask<P, ?, ?> task, P... params) {
        if (task instanceof Preemptable) {
            synchronized (mPreemptable) {
                mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task));
            }
            task.executeOnExecutor(mNonPreemptingExecutor, params);
        } else {
            task.executeOnExecutor(this, params);
        }
    }

    private Executor mNonPreemptingExecutor = new Executor() {
        @Override
        public void execute(Runnable command) {
            assert(command != null);
            mQueue.add(command);
        }
    };

    @Override
    public void execute(Runnable command) {
        preempt();
        assert(command != null);
        mQueue.add(command);
    }

    @Override
    public void run() {
        while (true) {
            try {
                final Runnable command = mQueue.take();
                command.run();
            } catch (InterruptedException e) {
                // That was weird; let's go look for more tasks.
            }
        }
    }
}
