//////////////////////////////////////////////////////////////////
// Объект одного атома цикла, наподобие CAtom, но с некоторыми
// переопределенными функциями
//////////////////////////////////////////////////////////////////
function CSpecCycleAtom()
{
	this.myCycle = null;	// ссылка на объект цикл
	this.cycleIndex=0;		// индекс этого атома в кольце цикла
	////////////////////////////////////////////////
	this.children=new Array();
	this.type="C";
	this.parent=null;
	this.drawType=1;
	this.x=0;
	this.y=0;
	this.rootDistance=0;
	this.linkType=0;
	this.freeLinks=4;
	this.firstChildDirection="down";
	this.molecule=null;
	this.oText=null;
	this.oLink=null;
	this.longestChild=null;
	this.longestChildCount=0;
	this.isOnMainLine=false;
	this.subtreeLength=0;
	this.isFlipped=false;	// атом повернут на 180 град.?
}
CSpecCycleAtom.prototype = new CAtom();

// Создает объект - атом
CSpecCycleAtom.prototype.create = function(atomType)
{
	var newAtom = new CSpecCycleAtom();
	newAtom.type = atomType;
	newAtom.linkType = 1;
	return newAtom;
}

// Добавляет дочерний элемент к атому
CSpecCycleAtom.prototype.CAtom_addChild = CAtom.prototype.addChild;
CSpecCycleAtom.prototype.addChild = function(atom)
{
	this.myCycle.children.push( atom);
	return this.CAtom_addChild( atom);
}
// Удаляет дочерний элемент
CSpecCycleAtom.prototype.CAtom_removeChild = CAtom.prototype.removeChild;
CSpecCycleAtom.prototype.removeChild = function(atom)
{
	this.myCycle.removeChild( atom);
	return this.CAtom_removeChild( atom);
}

// Возвращает массив сдвигов по координатам
CSpecCycleAtom.prototype.CAtom_getCommonChildDirectionsFor = CAtom.prototype.getCommonChildDirectionsFor;
CSpecCycleAtom.prototype.getCommonChildDirectionsFor = function(atom)
{
	var add = new Array();
	if( !this.isFlipped)
	{
		add.push("up");
		add.push("down");
	}
	else
	{
		add.push("down");
		add.push("up");
	}
	return add;
}
// Функция возвращает количество "занятых" связей
CSpecCycleAtom.prototype.CAtom_getLockedLinks = CAtom.prototype.getLockedLinks;
CSpecCycleAtom.prototype.getLockedLinks = function()
{
	var locked = 0;
	if( this.cycleIndex==0)
	{
		// кислород
		locked = 2;
	}
	else
	{
		// любой углерод атом
		locked = this.CAtom_getLockedLinks() + 2;
	}
	return locked;
}

// Создает визуальное представление атома
CSpecCycleAtom.prototype.CAtom_createVisual = CAtom.prototype.createVisual;
CSpecCycleAtom.prototype.createVisual = function(atomType)
{
	/*
	if( this.myCycle!=null && this.cycleIndex==0)
	{
		this.parent = this.myCycle;
		this.CAtom_createVisual(atomType);
		this.parent = null;
	}
	else
	{
		this.CAtom_createVisual(atomType);
	}
	*/
	var sPositions = this.myCycle.getAtomsPixelPositions();
	if( sPositions == null)
	{
		trace("#E00000 mc2D spec_cycle createVisual error: incorrect cycle type ["+this.myCycle.cycleType+"]");
		return;
	}
	this.CAtom_createVisual(atomType);

	var xy = this.molecule.board.getCellXY(this.myCycle.getAbsX(), this.myCycle.getAbsY());
	if( this.oText != null)
	{
		this.oText.x = xy.x + sPositions[ this.cycleIndex][0] - this.oText.getMediaSize().width/2 + 6;
		this.oText.y = xy.y + sPositions[ this.cycleIndex][1];
	}
	if( this.oLink != null)
	{
		this.oLink.hide();
	}
}
// Загружает нужную картинку связи
//CSpecCycleAtom.prototype.CAtom_loadLinkImage = CAtom.prototype.loadLinkImage;
CSpecCycleAtom.prototype.loadLinkImage=function()
{
}
// Возвращает ссылку на атом, который представляет this в дереве молекулы
CSpecCycleAtom.prototype.getVisualInstance = function()
{
	return this.myCycle;
}
// Смена типа связи
CSpecCycleAtom.prototype.CAtom_setLink = CAtom.prototype.setLink;
CSpecCycleAtom.prototype.setLink=function(alinkType)
{
	//??
}
//////////////////////////////////////////////////////////////////
// Объект цикла, наподобие CAtom, но с более сложной структурой
//////////////////////////////////////////////////////////////////
function CSpecCycle()
{
	this.cycleType = 6;	// количество атомов в цикле
	this.cycleChildren = new Array;	// массив ссылок на атомы цикла, включая себя
	this.oImage = null;
	////////////////////////////////////////////////
	this.children=new Array();
	this.type="C";
	this.parent=null;
	this.drawType=1;
	this.x=0;
	this.y=0;
	this.rootDistance=0;
	this.linkType=0;
	this.freeLinks=4;
	this.firstChildDirection="down";
	this.molecule=null;
	this.oText=null;
	this.oLink=null;
	this.longestChild=null;
	this.longestChildCount=0;
	this.isOnMainLine=false;
	this.subtreeLength=0;
	this.index=0;
	this.isFlipped=false;	// атом повернут на 180 град.?
}

CSpecCycle.prototype = new CAtom();
// Создает новый объект-цикл
CSpecCycle.prototype.CAtom_create = CAtom.prototype.create;
CSpecCycle.prototype.create = function( atomType)
{
trace("#0000E0 **************************");
trace("#0000E0 ******* CSpecCycle *******");
trace("#0000E0 **************************");

	var newCycle = new CSpecCycle();
	if( typeof(atomType)!="string" || atomType.length<3 || atomType.indexOf("_")==-1)
	{
		trace("mc2D spec_cycle creation error: incorrect cycle type ["+atomType+"]");
		return null;
	}
	var cells = atomType.split("_");
	var cycleType = cells[0];
	var cycleNumber = Number(cells[1]);

	newCycle.type = atomType;
	newCycle.cycleType = cycleNumber;

	if( cycleNumber<5 || cycleNumber>6)
	{
		trace("mc2D spec_cycle creation error: incorrect cycle count ["+cycleNumber+"]");
		return null;
	}

	for( var i=0; i<cycleNumber + 0 /*NO!!! fake atom*/; i++)
	{
		// Создает объект - атом
		var newAtom = CSpecCycleAtom.prototype.create(i==0?"O":cycleType);
		newAtom.myCycle = newCycle;
		newAtom.cycleIndex = i;

		newCycle.cycleChildren.push( newAtom);
		/*if( i > 0)
		{
			newCycle.cycleChildren[i-1].addChild( newCycle.cycleChildren[i]);
		}
		if( i == cycleNumber)
		{
			newAtom.isTail = true;
		}*/
	}
trace("#00FF00 newCycle.type="+newCycle.type);
	return newCycle;
};
/*
// Удаляет дочерний элемент
CSpecCycle.prototype.CAtom_removeChild = CAtom.prototype.removeChild;
CSpecCycle.prototype.removeChild = function(atom)
{
	return this.CAtom_removeChild( atom);
}
*/

// Возвращает сдвиги в пикселях для атомов цикла
CSpecCycle.prototype.getAtomsPixelPositions = function()
{
	var sPositions = null;
	if( this.cycleType == 5)
	{
		sPositions = new Array(
			new Array(84,-7),
			new Array(24,-7),
			new Array(-9,25),
			new Array(56,53),
			new Array(120,25)
		);
	}
	else	if( this.cycleType == 6)
	{
		var dy = -8;
		sPositions = new Array(
			new Array(72,1+dy),
			new Array(20,1+dy),
			new Array(-8,31+dy),
			new Array(51,60+dy),
			new Array(91,60+dy),
			new Array(121,31+dy)
		);
	}
	else
		return null;
	return sPositions;
}


// Возвращает массив объектов с координатами клеток, занимаемых атомом
CSpecCycle.prototype.getOccupiedBoardCells = function()
{
	var cells = new Array();
	// ячейка, занимаемая атомом
	return cells;
}
// Устанавливает координату X
CSpecCycle.prototype.CAtom_setX = CAtom.prototype.setX;
CSpecCycle.prototype.setX=function(ax)
{
	this.CAtom_setX( ax);
	//if( this.myCycle == null)	return;
	var sPositions = this.getAtomsPixelPositions();
	if( sPositions == null)
	{
		trace("#E00000 mc2D spec_cycle createVisual error: incorrect cycle type ["+this.myCycle.cycleType+"]");
		return;
	}
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		var cellShift = this.molecule.board.getXYCell(sPositions[i][0], sPositions[i][1]);
		child.setX( ax + cellShift.x);
trace("cellShift xy="+cellShift.x+","+cellShift.y);
	}
}
// Устанавливает координату Y
CSpecCycle.prototype.CAtom_setY = CAtom.prototype.setY;
CSpecCycle.prototype.setY=function(ay)
{
	this.CAtom_setY( ay);
	//if( this.myCycle == null)	return;
	var sPositions = this.getAtomsPixelPositions();
	if( sPositions == null)
	{
		trace("#E00000 mc2D spec_cycle createVisual error: incorrect cycle type ["+this.myCycle.cycleType+"]");
		return;
	}
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		var cellShift = this.molecule.board.getXYCell(sPositions[i][0], sPositions[i][1]);
		child.setY( ay + cellShift.y);
	}
}
// Создает визуальное представление атома
CSpecCycle.prototype.CAtom_createVisual = CAtom.prototype.createVisual;
CSpecCycle.prototype.createVisual = function(atomType)
{
trace("#FF0000******************************************************");
trace("#FF0000******************************************************");
	// Создадим картинку цикла
	if( this.oImage == null)
	{
		this.oImage = new Image();
		this.oImage.enabled = false;
		if( this.cycleType == 5)
			this.oImage.src = this.molecule.rmmlParent.getImagePath("specCycle5.png");
		else	if( this.cycleType == 6)
			this.oImage.src = this.molecule.rmmlParent.getImagePath("specCycle6.png");
		this.oImage.parent = this.molecule.rmmlParent;
		var xy = this.molecule.board.getCellXY(this.getAbsX(), this.getAbsY());
		this.oImage.x = xy.x;
		this.oImage.y = xy.y;
	}
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		this.cycleChildren[i].molecule = this.molecule;
		this.cycleChildren[i].createVisual();
	}
	this.CAtom_createVisual("");
	if( this.oText!=null)	this.oText.hide();
	if( this.oLink!=null)	this.oLink.hide();
}
// устанавливает флаг расположения первого атома
//CSpecCycle.prototype.CAtom_setFirstChildDirection = CAtom.prototype.setFirstChildDirection;
CSpecCycle.prototype.setFirstChildDirection = function(aDir)
{
	trace("#0000E0 1. **************************************");
}
//
CSpecCycle.prototype.updateInternalChildDirections = function()
{
	//??
}
// Возвращает границы объекта
CSpecCycle.prototype.getBounds = function()
{
	var bounds=new Object();
		bounds.left = 0;
		bounds.right = 0;
		bounds.top = 0;
		bounds.bottom = 0;
	if( this.oImage == null)
	{
		return bounds;
	}
	var lt = this.molecule.board.getXYCell(this.oImage.x, this.oImage.y);
	var rb = this.molecule.board.getXYCell( this.oImage.x+this.oImage.width,
											this.oImage.y+this.oImage.height);
	bounds.left = lt.x - this.molecule.x;
	bounds.right = rb.x - this.molecule.x;
	bounds.top = lt.y - this.molecule.y;
	bounds.bottom = rb.y - this.molecule.y;
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		var childBounds = this.cycleChildren[i].getBounds();
		if( bounds.left>childBounds.left)		bounds.left=childBounds.left;
		if( bounds.top>childBounds.top)			bounds.top=childBounds.top;
		if( bounds.right<childBounds.right)		bounds.right=childBounds.right;
		if( bounds.bottom<childBounds.bottom)	bounds.bottom=childBounds.bottom;
	}
	bounds.left--;
	return bounds;
}
// Расчет длинн поддеревьев
CSpecCycle.prototype.calculateLengths=function()
{
	this.longestChildCount = 0;
	this.longestChild = null;
}
// считает расстояние от атома до корня молекулы
CSpecCycle.prototype.CAtom_calculateDistances = CAtom.prototype.calculateDistances;
CSpecCycle.prototype.calculateDistances = function()
{
	this.CAtom_calculateDistances();
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.rootDistance = this.rootDistance + 1;
	}
}
// Возвращает длину максимальной цепочки, возможно из двух поддеревьев и сортирует ветки
CSpecCycle.prototype.optimizeLongestChildCount = function()
{
	return 0;
}
// Копирует параметры с другого цикла
CSpecCycle.prototype.copyFrom = function(atom)
{
	this.type = atom.type;
	this.cycleType = atom.cycleType;
	this.linkType = atom.linkType;
	this.isFlipped = atom.isFlipped;

	for( var i=0; i<atom.cycleChildren.length; i++)
	{
		var cycleAtom = new CSpecCycleAtom();
		cycleAtom.myCycle = this;
		cycleAtom.copyFrom( atom.cycleChildren[i]);

		atom.cycleChildren[i].createdCopy = cycleAtom;

		this.cycleChildren.push( cycleAtom);
		cycleAtom.cycleIndex = i;

		/*if( i > 0)
		{
			this.cycleChildren[i-1].addChild( cycleAtom);
		}
		cycleAtom.isTail = atom.cycleChildren[i].isTail;*/
	}
	this.children.length = 0;
}
// устанавливает стиль текста
CSpecCycle.prototype.setTextStyle = function(stl)
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.setTextStyle( stl);
	}
}
// возвращает количество хим элементов этого атома
CSpecCycle.prototype.getElementCount = function(elem)
{
trace("#FF0000 CSpecCycle.prototype.getElementCount("+elem+")");
	var count = 0;
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		count += child.getElementCount( elem);
	}
	return count;
}
// возвращает головной атом цикла
CSpecCycle.prototype.head = function()
{
	return this.cycleChildren[0];
}
// возвращает конечный фейковый атом цикла
CSpecCycle.prototype.tail = function()
{
	trace("#0000E0 2. **************************************");
}
// Удаление графического представления молекулы
CSpecCycle.prototype.destroy=function()
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.destroy();
	}
	if( this.oImage != null)
	{
		this.oImage.parent = null;
		this.oImage = null;
	}
}
// Добавляет флаг видимого типа
CSpecCycle.prototype.CAtom_addDrawType = CAtom.prototype.addDrawType;
CSpecCycle.prototype.addDrawType = function( atype)
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.addDrawType( atype);
	}
	this.CAtom_addDrawType( atype);
}
// Снимает флаг видимого типа
CSpecCycle.prototype.CAtom_removeDrawType = CAtom.prototype.removeDrawType;
CSpecCycle.prototype.removeDrawType = function( atype)
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.removeDrawType( atype);
	}
	this.CAtom_removeDrawType( atype);
}
// Устанавливает основное значение видимого типа
CSpecCycle.prototype.CAtom_setDrawStyle = CAtom.prototype.setDrawStyle;
CSpecCycle.prototype.setDrawStyle = function( atype)
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.setDrawStyle( atype);
	}
	this.CAtom_setDrawStyle( atype);
}
// Устанавливает дополнительное значение видимого типа
CSpecCycle.prototype.CAtom_setExtendedDrawStyle = CAtom.prototype.setExtendedDrawStyle;
CSpecCycle.prototype.setExtendedDrawStyle = function( atype)
{
	for( var i=0; i<this.cycleChildren.length; i++)
	{
		var child = this.cycleChildren[i];
		child.setExtendedDrawStyle( atype);
	}
	this.CAtom_setExtendedDrawStyle( atype);
}
// Функция возвращает количество "занятых" связей
CSpecCycle.prototype.getLockedLinks = function()
{
	trace("#0000E0 3. **************************************");
	return 100;
}
//
CSpecCycle.prototype.allowAddition = function(atomType)
{
	trace("#0000E0 4. **************************************");
	return false;
}
// Меняем порядок в атомах
CSpecCycle.prototype.makeHead = function(atom)
{
	trace("#0000E0 5. **************************************");
}
// Переопределяем для сдвига картинки
CSpecCycle.prototype.CAtom_showH = CAtom.prototype.showH;
CSpecCycle.prototype.showH = function()
{
	if( this.oImage != null)
	{
		var xy = this.molecule.board.getCellXY(this.getAbsX(), this.getAbsY());
		this.oImage.x = xy.x;
		this.oImage.y = xy.y;
	}
	this.CAtom_showH();
}