/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
#include "StdAfx.h"
#include "mgGL/Appearance.h"
#include "topo/BVertex.h"
#include "topo/Edge.h"

#if defined(_DEBUG)
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//
//Implements MGBCell Class.
//Cell is a cell without boundaries(No Boundaries).
//Boundaries are defined in the subclass, MGEdge, or MGFace.

//There are two types of cells. One is a parameter cell(pcell) and
//the other is a binder cell(bcell). They are exclusive, that is, if
//a cell is a parameter cell, the cell cannot be binder cell and
//vice versa.
//Binder cell is a binder of parameter cells. Plural cells are connected
//through a binder.
//MGBCell is an abstract class.

MGBCell::MGBCell(const MGBCell& cell){ ; }//We release all of the partner members.
MGBCell& MGBCell::operator=(const MGBCell& gel2){ m_partners.clear(); return *this; }
MGBCell::MGBCell(const MGPCell* pcell):m_partners(1, pcell){ ; }
MGBCell::MGBCell(std::vector<const MGPCell*>& pcells):m_partners(pcells){;}//Construct of partner member of pcells.
MGBCell::MGBCell(MGBCell&& rhs){ ; }//Move constructor.
MGBCell& MGBCell::operator=(MGBCell&& rhs){ m_partners.clear(); return *this; }//Move assignment.

///Assignment.

///When the leaf objects of this and gel2 are not equal, this assignment
///does nothing.
MGGel& MGBCell::operator=(const MGGel& gel2){
	MGBCell* bcel = dynamic_cast<MGBCell*>(this);
	if(bcel)
		(*this) = *bcel;
	return *this;
}

//Add partner to this binder cell.
void MGBCell::add_partner_member(const MGPCell& partner){
	size_t npartners = m_partners.size();
	if(npartners<=0)
		m_partners.push_back(&partner);
	else{
		auto comp= [](const MGPCell* cell1, const MGPCell* cell2) {
			return cell1->is_less_than(*cell2); };
		std::vector<const MGPCell*>::iterator
			i=std::lower_bound(m_partners.begin(),m_partners.end(),&partner, comp);
		m_partners.insert(i,&partner);
	}
}

//Obtain the 1st partner member.
//When this had no partners, null is returned.
const MGPCell* MGBCell::first_partner_member()const{
	const MGPCell* pcel = nullptr;
	if(m_partners.size())
		pcel= m_partners[0];
	return pcel;
}

//Free specified partner(const_iterator).
void MGBCell::free_partner_member(const_iterator itrin) const{
	int i=(int)(itrin-m_partners.begin());
	const_iterator itr_next=itrin; itr_next++;
	const_iterator itre=m_partners.end();
	while(itr_next!=itre)
		m_partners[i++]=(*itr_next++);
	m_partners.pop_back();
}

//Free specified partner(cellin).
void MGBCell::free_partner_member(const MGPCell* cellin) const{
	const_iterator itr=m_partners.begin();
	const_iterator itre=m_partners.end();
	for(; itr!=itre; itr++){
		if(cellin==*itr){
			free_partner_member(itr);
			break;
		}
	}
}

// Output virtual function.
std::ostream& MGBCell::toString(std::ostream& ostrm) const{
	std::string bcellName;
	size_t n = m_partners.size();
	if(n){
		const MGPCell* pcel = m_partners[0];
		if(pcel)
			bcellName = pcel->whoami();
	}
	ostrm<<",BCell::partnerMemeber"<<bcellName<<"s="<<n;
	MGBCell::const_iterator ps=m_partners.begin(),	pe=m_partners.end();
	if(ps!=pe){
		const MGPCell* pcel0 = *ps;
		ostrm<<"=[";
		ostrm<<(MGGel*)pcel0;
		for(ps++; ps!=pe; ps++)
			ostrm<<","<<(MGGel*)(*ps);
		ostrm<<"]";
	}
	return ostrm;
}
