#pragma once
#include <functional>

//! Entrypoint interface for registering media file types that can be opened through "open file" dialogs or associated with foobar2000 application in Windows shell. \n
//! Instead of implementing this directly, use DECLARE_FILE_TYPE() / DECLARE_FILE_TYPE_EX() macros.
class input_file_type : public service_base {
public:
	virtual unsigned get_count()=0;
	virtual bool get_name(unsigned idx,pfc::string_base & out)=0;//eg. "MPEG files"
	virtual bool get_mask(unsigned idx,pfc::string_base & out)=0;//eg. "*.MP3;*.MP2"; separate with semicolons
	virtual bool is_associatable(unsigned idx) = 0;
	
	static void for_each_media_ext( std::function<void (const char*)>, bool bDotExt = false);

#if FOOBAR2000_TARGET_VERSION >= 76
	static void build_openfile_mask(pfc::string_base & out,bool b_include_playlists=true, bool b_include_archives = false);
	static void make_extension_support_fingerprint(pfc::string_base & str);
	static void make_filetype_support_fingerprint(pfc::string_base & str);
#endif

	FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(input_file_type);
};

//! Extended interface for registering media file types that can be associated with foobar2000 application in Windows shell. \n
//! Instead of implementing this directly, use DECLARE_FILE_TYPE() / DECLARE_FILE_TYPE_EX() macros.
class input_file_type_v2 : public input_file_type {
public:
	virtual void get_format_name(unsigned idx, pfc::string_base & out, bool isPlural) = 0;
	virtual void get_extensions(unsigned idx, pfc::string_base & out) = 0;

	//Deprecated input_file_type method implementations:
	bool get_name(unsigned idx, pfc::string_base & out) {get_format_name(idx, out, true); return true;}
	bool get_mask(unsigned idx, pfc::string_base & out) {
		pfc::string_formatter temp; get_extensions(idx,temp);
		pfc::chain_list_v2_t<pfc::string> exts; pfc::splitStringSimple_toList(exts,";",temp);
		if (exts.get_count() == 0) return false;//should not happen
		temp.reset();
		for(auto walk = exts.cfirst(); walk.is_valid(); ++walk) {
			if (!temp.is_empty()) temp << ";";
			temp << "*." << walk->get_ptr();
		}
		out = temp;
		return true;
	}

	FB2K_MAKE_SERVICE_INTERFACE(input_file_type_v2,input_file_type)
};


//! Implementation helper.
class input_file_type_impl : public input_file_type
{
	const char * name, * mask;
	bool m_associatable;
public:
	input_file_type_impl(const char * p_name, const char * p_mask,bool p_associatable) : name(p_name), mask(p_mask), m_associatable(p_associatable) {}
	unsigned get_count() {return 1;}
	bool get_name(unsigned idx,pfc::string_base & out) {if (idx==0) {out = name; return true;} else return false;}
	bool get_mask(unsigned idx,pfc::string_base & out) {if (idx==0) {out = mask; return true;} else return false;}
	bool is_associatable(unsigned idx) {return m_associatable;}
};


//! Helper macro for registering our media file types.
//! Usage: DECLARE_FILE_TYPE("Blah files","*.blah;*.bleh");
#define DECLARE_FILE_TYPE(NAME,MASK) FB2K_SERVICE_FACTORY_PARAMS(input_file_type_impl, NAME, MASK, true)


//! Implementation helper.
//! Usage: static input_file_type_factory mytype("blah type","*.bla;*.meh",true);
class input_file_type_factory : private service_factory_single_transparent_t<input_file_type_impl>
{
public:
	input_file_type_factory(const char * p_name,const char * p_mask,bool p_associatable)
		: service_factory_single_transparent_t<input_file_type_impl>(p_name,p_mask,p_associatable) {}
};



class input_file_type_v2_impl : public input_file_type_v2 {
public:
	input_file_type_v2_impl(const char * extensions,const char * name, const char * namePlural) : m_name(name), m_namePlural(namePlural), m_extensions(extensions) {}
	unsigned get_count() {return 1;}
	bool is_associatable(unsigned idx) {return true;}
	void get_format_name(unsigned idx, pfc::string_base & out, bool isPlural) {
		out = isPlural ? m_namePlural : m_name;
	}
	void get_extensions(unsigned idx, pfc::string_base & out) {
		out = m_extensions;
	}

private:
	const pfc::string8 m_name, m_namePlural, m_extensions;
};

//! Helper macro for registering our media file types, extended version providing separate singular/plural type names.
//! Usage: DECLARE_FILE_TYPE_EX("mp1;mp2;mp3","MPEG file","MPEG files")
#define DECLARE_FILE_TYPE_EX(extensions, name, namePlural) FB2K_SERVICE_FACTORY_PARAMS(input_file_type_v2_impl, extensions, name, namePlural)

//! Service for registering protocol types that can be associated with foobar2000.
class input_protocol_type : public service_base {
	FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(input_protocol_type)
public:
	//! Returns the name of the protocol, such as "ftp" or "http".
	virtual void get_protocol_name(pfc::string_base & out) = 0;
	//! Returns a human-readable description of the protocol.
	virtual void get_description(pfc::string_base & out) = 0;
};
