// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#include "Context.hpp"

#include "EventListener.hpp"
#include "File.hpp"
#include "Thread.hpp"
#include "Variable.hpp"
#include "WeakMap.hpp"

#include <memory>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <unordered_set>

namespace {

////////////////////////////////////////////////////////////////////////////////
// Broadcaster - template base class for ServerEventBroadcaster and
// ClientEventBroadcaster
////////////////////////////////////////////////////////////////////////////////
template<typename Listener>
class Broadcaster : public Listener
{
public:
	void add(Listener *);
	void remove(Listener *);

protected:
	template<typename F>
	inline void foreach(F &&);

	template<typename F>
	inline void modify(F &&);

	using ListenerSet = std::unordered_set<Listener *>;
	std::recursive_mutex mutex;
	std::shared_ptr<ListenerSet> listeners = std::make_shared<ListenerSet>();
	int listenersInUse = 0;
};

template<typename Listener>
void Broadcaster<Listener>::add(Listener *l)
{
	modify([&]() { listeners->emplace(l); });
}

template<typename Listener>
void Broadcaster<Listener>::remove(Listener *l)
{
	modify([&]() { listeners->erase(l); });
}

template<typename Listener>
template<typename F>
void Broadcaster<Listener>::foreach(F &&f)
{
	std::unique_lock<std::recursive_mutex> lock(mutex);
	++listenersInUse;
	auto copy = listeners;
	for(auto l : *copy) { f(l); }
	--listenersInUse;
}

template<typename Listener>
template<typename F>
void Broadcaster<Listener>::modify(F &&f)
{
	std::unique_lock<std::recursive_mutex> lock(mutex);
	if(listenersInUse > 0)
	{
		// The listeners map is current being iterated over.
		// Make a copy before making the edit.
		listeners = std::make_shared<ListenerSet>(*listeners);
	}
	f();
}

////////////////////////////////////////////////////////////////////////////////
// ServerEventBroadcaster
////////////////////////////////////////////////////////////////////////////////
class ServerEventBroadcaster : public Broadcaster<vk::dbg::ServerEventListener>
{
public:
	using Thread = vk::dbg::Thread;

	void onThreadStarted(Thread::ID id) override
	{
		foreach([&](auto *l) { l->onThreadStarted(id); });
	}

	void onThreadStepped(Thread::ID id) override
	{
		foreach([&](auto *l) { l->onThreadStepped(id); });
	}

	void onLineBreakpointHit(Thread::ID id) override
	{
		foreach([&](auto *l) { l->onLineBreakpointHit(id); });
	}

	void onFunctionBreakpointHit(Thread::ID id) override
	{
		foreach([&](auto *l) { l->onFunctionBreakpointHit(id); });
	}
};

////////////////////////////////////////////////////////////////////////////////
// ClientEventBroadcaster
////////////////////////////////////////////////////////////////////////////////
class ClientEventBroadcaster : public Broadcaster<vk::dbg::ClientEventListener>
{
public:
	void onSetBreakpoint(const vk::dbg::Location &location, bool &handled) override
	{
		foreach([&](auto *l) { l->onSetBreakpoint(location, handled); });
	}

	void onSetBreakpoint(const std::string &func, bool &handled) override
	{
		foreach([&](auto *l) { l->onSetBreakpoint(func, handled); });
	}

	void onBreakpointsChanged() override
	{
		foreach([&](auto *l) { l->onBreakpointsChanged(); });
	}
};

}  // namespace

namespace vk {
namespace dbg {

////////////////////////////////////////////////////////////////////////////////
// Context::Impl
////////////////////////////////////////////////////////////////////////////////
class Context::Impl : public Context
{
public:
	// Context compliance
	Lock lock() override;
	void addListener(ClientEventListener *) override;
	void removeListener(ClientEventListener *) override;
	ClientEventListener *clientEventBroadcast() override;
	void addListener(ServerEventListener *) override;
	void removeListener(ServerEventListener *) override;
	ServerEventListener *serverEventBroadcast() override;

	void addFile(const std::shared_ptr<File> &file);

	ServerEventBroadcaster serverEventBroadcaster;
	ClientEventBroadcaster clientEventBroadcaster;

	std::mutex mutex;
	std::unordered_map<std::thread::id, std::shared_ptr<Thread>> threadsByStdId;
	std::unordered_set<std::string> functionBreakpoints;
	std::unordered_map<std::string, std::vector<int>> pendingBreakpoints;
	WeakMap<Thread::ID, Thread> threads;
	WeakMap<File::ID, File> files;
	WeakMap<Frame::ID, Frame> frames;
	WeakMap<Scope::ID, Scope> scopes;
	WeakMap<VariableContainer::ID, VariableContainer> variableContainers;
	Thread::ID nextThreadID = 1;
	File::ID nextFileID = 1;
	Frame::ID nextFrameID = 1;
	Scope::ID nextScopeID = 1;
	VariableContainer::ID nextVariableContainerID = 1;
};

Context::Lock Context::Impl::lock()
{
	return Lock(this);
}

void Context::Impl::addListener(ClientEventListener *l)
{
	clientEventBroadcaster.add(l);
}

void Context::Impl::removeListener(ClientEventListener *l)
{
	clientEventBroadcaster.remove(l);
}

ClientEventListener *Context::Impl::clientEventBroadcast()
{
	return &clientEventBroadcaster;
}

void Context::Impl::addListener(ServerEventListener *l)
{
	serverEventBroadcaster.add(l);
}

void Context::Impl::removeListener(ServerEventListener *l)
{
	serverEventBroadcaster.remove(l);
}

ServerEventListener *Context::Impl::serverEventBroadcast()
{
	return &serverEventBroadcaster;
}

void Context::Impl::addFile(const std::shared_ptr<File> &file)
{
	files.add(file->id, file);

	auto it = pendingBreakpoints.find(file->name);
	if(it != pendingBreakpoints.end())
	{
		for(auto line : it->second)
		{
			file->addBreakpoint(line);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Context
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<Context> Context::create()
{
	return std::shared_ptr<Context>(new Context::Impl());
}

////////////////////////////////////////////////////////////////////////////////
// Context::Lock
////////////////////////////////////////////////////////////////////////////////
Context::Lock::Lock(Impl *ctx)
    : ctx(ctx)
{
	ctx->mutex.lock();
}

Context::Lock::Lock(Lock &&o)
    : ctx(o.ctx)
{
	o.ctx = nullptr;
}

Context::Lock::~Lock()
{
	unlock();
}

Context::Lock &Context::Lock::operator=(Lock &&o)
{
	ctx = o.ctx;
	o.ctx = nullptr;
	return *this;
}

void Context::Lock::unlock()
{
	if(ctx)
	{
		ctx->mutex.unlock();
		ctx = nullptr;
	}
}

std::shared_ptr<Thread> Context::Lock::currentThread()
{
	auto threadIt = ctx->threadsByStdId.find(std::this_thread::get_id());
	if(threadIt != ctx->threadsByStdId.end())
	{
		return threadIt->second;
	}
	auto id = ++ctx->nextThreadID;
	char name[256];
	snprintf(name, sizeof(name), "Thread<0x%x>", id.value());

	auto thread = std::make_shared<Thread>(id, ctx);
	ctx->threads.add(id, thread);
	thread->setName(name);
	ctx->threadsByStdId.emplace(std::this_thread::get_id(), thread);

	ctx->serverEventBroadcast()->onThreadStarted(id);

	return thread;
}

std::shared_ptr<Thread> Context::Lock::get(Thread::ID id)
{
	return ctx->threads.get(id);
}

std::vector<std::shared_ptr<Thread>> Context::Lock::threads()
{
	std::vector<std::shared_ptr<Thread>> out;
	out.reserve(ctx->threads.approx_size());
	for(auto it : ctx->threads)
	{
		out.push_back(it.second);
	}
	return out;
}

std::shared_ptr<File> Context::Lock::createVirtualFile(const std::string &name,
                                                       const std::string &source)
{
	auto file = File::createVirtual(ctx->nextFileID++, name, source);
	ctx->addFile(file);
	return file;
}

std::shared_ptr<File> Context::Lock::createPhysicalFile(const std::string &path)
{
	auto file = File::createPhysical(ctx->nextFileID++, path);
	ctx->addFile(file);
	return file;
}

std::shared_ptr<File> Context::Lock::get(File::ID id)
{
	return ctx->files.get(id);
}

std::vector<std::shared_ptr<File>> Context::Lock::files()
{
	std::vector<std::shared_ptr<File>> out;
	out.reserve(ctx->files.approx_size());
	for(auto it : ctx->files)
	{
		out.push_back(it.second);
	}
	return out;
}

std::shared_ptr<Frame> Context::Lock::createFrame(
    const std::shared_ptr<File> &file, std::string function)
{
	auto frame = std::make_shared<Frame>(ctx->nextFrameID++, std::move(function));
	ctx->frames.add(frame->id, frame);
	frame->arguments = createScope(file);
	frame->locals = createScope(file);
	frame->registers = createScope(file);
	frame->hovers = createScope(file);
	return frame;
}

std::shared_ptr<Frame> Context::Lock::get(Frame::ID id)
{
	return ctx->frames.get(id);
}

std::shared_ptr<Scope> Context::Lock::createScope(
    const std::shared_ptr<File> &file)
{
	auto scope = std::make_shared<Scope>(ctx->nextScopeID++, file, std::make_shared<VariableContainer>());
	ctx->scopes.add(scope->id, scope);
	return scope;
}

std::shared_ptr<Scope> Context::Lock::get(Scope::ID id)
{
	return ctx->scopes.get(id);
}

void Context::Lock::track(const std::shared_ptr<VariableContainer> &vc)
{
	ctx->variableContainers.add(vc->id, vc);
}

std::shared_ptr<VariableContainer> Context::Lock::get(VariableContainer::ID id)
{
	return ctx->variableContainers.get(id);
}

void Context::Lock::addFunctionBreakpoint(const std::string &name)
{
	ctx->functionBreakpoints.emplace(name);
}

void Context::Lock::addPendingBreakpoints(const std::string &filename, const std::vector<int> &lines)
{
	ctx->pendingBreakpoints.emplace(filename, lines);
}

bool Context::Lock::isFunctionBreakpoint(const std::string &name)
{
	return ctx->functionBreakpoints.count(name) > 0;
}

}  // namespace dbg
}  // namespace vk
