#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cassert>
#include <cmath>

#include <kms++/kms++.h>
#include "helpers.h"

using namespace std;

namespace kms
{

#ifndef DRM_MODE_CONNECTOR_DPI
#define DRM_MODE_CONNECTOR_DPI 17
#endif

static const map<int, string> connector_names = {
	{ DRM_MODE_CONNECTOR_Unknown, "Unknown" },
	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
	{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
	{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
	{ DRM_MODE_CONNECTOR_Composite, "Composite" },
	{ DRM_MODE_CONNECTOR_SVIDEO, "S-Video" },
	{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
	{ DRM_MODE_CONNECTOR_Component, "Component" },
	{ DRM_MODE_CONNECTOR_9PinDIN, "9-Pin-DIN" },
	{ DRM_MODE_CONNECTOR_DisplayPort, "DP" },
	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
	{ DRM_MODE_CONNECTOR_TV, "TV" },
	{ DRM_MODE_CONNECTOR_eDP, "eDP" },
	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
	{ DRM_MODE_CONNECTOR_DSI, "DSI" },
	{ DRM_MODE_CONNECTOR_DPI, "DPI" },
};

static const map<int, string> connection_str = {
	{ 0, "<unknown>" },
	{ DRM_MODE_CONNECTED, "Connected" },
	{ DRM_MODE_DISCONNECTED, "Disconnected" },
	{ DRM_MODE_UNKNOWNCONNECTION, "Unknown" },
};

static const map<int, string> subpix_str = {
#define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c }
	DEF_SUBPIX(UNKNOWN),
	DEF_SUBPIX(HORIZONTAL_RGB),
	DEF_SUBPIX(HORIZONTAL_BGR),
	DEF_SUBPIX(VERTICAL_RGB),
	DEF_SUBPIX(VERTICAL_BGR),
	DEF_SUBPIX(NONE),
#undef DEF_SUBPIX
};

struct ConnectorPriv
{
	drmModeConnectorPtr drm_connector;
};

Connector::Connector(Card &card, uint32_t id, uint32_t idx)
	:DrmPropObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx)
{
	m_priv = new ConnectorPriv();

	m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
	assert(m_priv->drm_connector);

	// XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id.
	// XXX So refresh the props again here.
	refresh_props();

	const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
	m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id);
}

Connector::~Connector()
{
	drmModeFreeConnector(m_priv->drm_connector);
	delete m_priv;
}

void Connector::refresh()
{
	drmModeFreeConnector(m_priv->drm_connector);

	m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
	assert(m_priv->drm_connector);

	// XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id.
	// XXX So refresh the props again here.
	refresh_props();

	const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
	m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id);
}

void Connector::setup()
{
	if (m_priv->drm_connector->encoder_id != 0)
		m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id);
	else
		m_current_encoder = 0;

	if (m_current_encoder)
		m_saved_crtc = m_current_encoder->get_crtc();
	else
		m_saved_crtc = 0;
}

void Connector::restore_mode()
{
	if (m_saved_crtc)
		m_saved_crtc->restore_mode(this);
}

Videomode Connector::get_default_mode() const
{
	if (m_priv->drm_connector->count_modes == 0)
		throw invalid_argument("no modes available\n");
	drmModeModeInfo drmmode = m_priv->drm_connector->modes[0];

	return drm_mode_to_video_mode(drmmode);
}

Videomode Connector::get_mode(const string& mode) const
{
	auto c = m_priv->drm_connector;

	size_t idx = mode.find('@');

	string name = idx == string::npos ? mode : mode.substr(0, idx);
	float vrefresh = idx == string::npos ? 0.0 : stod(mode.substr(idx + 1));

	for (int i = 0; i < c->count_modes; i++) {
		Videomode m = drm_mode_to_video_mode(c->modes[i]);

		if (m.name != name)
			continue;

		if (vrefresh && vrefresh != m.calculated_vrefresh())
			continue;

		return m;
	}

	throw invalid_argument(mode + ": mode not found");
}

Videomode Connector::get_mode(unsigned xres, unsigned yres, float vrefresh, bool ilace) const
{
	auto c = m_priv->drm_connector;

	for (int i = 0; i < c->count_modes; i++) {
		Videomode m = drm_mode_to_video_mode(c->modes[i]);

		if (m.hdisplay != xres || m.vdisplay != yres)
			continue;

		if (ilace != m.interlace())
			continue;

		if (vrefresh && vrefresh != m.calculated_vrefresh())
			continue;

		return m;
	}

	// If not found, do another round using rounded vrefresh

	for (int i = 0; i < c->count_modes; i++) {
		Videomode m = drm_mode_to_video_mode(c->modes[i]);

		if (m.hdisplay != xres || m.vdisplay != yres)
			continue;

		if (ilace != m.interlace())
			continue;

		if (vrefresh && vrefresh != roundf(m.calculated_vrefresh()))
			continue;

		return m;
	}

	throw invalid_argument("mode not found");
}

bool Connector::connected() const
{
	return m_priv->drm_connector->connection == DRM_MODE_CONNECTED ||
			m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION;
}

vector<Crtc*> Connector::get_possible_crtcs() const
{
	vector<Crtc*> crtcs;

	for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) {
		auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);

		auto l = enc->get_possible_crtcs();

		crtcs.insert(crtcs.end(), l.begin(), l.end());
	}

	return crtcs;
}

Crtc* Connector::get_current_crtc() const
{
	if (m_current_encoder)
		return m_current_encoder->get_crtc();
	else
		return 0;
}

uint32_t Connector::connector_type() const
{
	return m_priv->drm_connector->connector_type;
}

uint32_t Connector::connector_type_id() const
{
	return m_priv->drm_connector->connector_type_id;
}

uint32_t Connector::mmWidth() const
{
	return m_priv->drm_connector->mmWidth;
}

uint32_t Connector::mmHeight() const
{
	return m_priv->drm_connector->mmHeight;
}

uint32_t Connector::subpixel() const
{
	return m_priv->drm_connector->subpixel;
}

const string& Connector::subpixel_str() const
{
	return subpix_str.at(subpixel());
}

std::vector<Videomode> Connector::get_modes() const
{
	vector<Videomode> modes;

	for (int i = 0; i < m_priv->drm_connector->count_modes; i++)
		modes.push_back(drm_mode_to_video_mode(
					m_priv->drm_connector->modes[i]));

	return modes;
}

std::vector<Encoder*> Connector::get_encoders() const
{
	vector<Encoder*> encoders;

	for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) {
		auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
		encoders.push_back(enc);
	}
	return encoders;
}

}
