#include "_Global.h"

#include "Main.h"

/**
 * ステージ
 */
class MyStage {
	var m;
	var g;

	var chip = 1;				// パーツ画像の横方向チップ数
	var line = 1;				//
	var base = 1;				// ベース判定用
	var bg_image;			// 背景イメージ
	var base_data;			// ベース情報
	var base_image;			// ベース画像
	var base_x, base_y;			//
	var back_image = -1;	// 背景イメージ
	var enemy;				// 敵情報
	var enemy_size;				//
	var _attack;				// 最後に攻撃した敵のインデックス
	var attack_x, attack_y;		// 自機が攻撃した位置
	var attack_x1, attack_y1;	//
	var attack_x2, attack_y2;	//
	var pattern;

	// ウィンドウ左上座標を確認
//	function win_x() { return m._win_x; }
//	function win_y() { return m._win_y; }

	/**
	 * コンストラクタ
	 */
	function MyStage(m) {
		this.m = m;
		g = m.g;

		var i;
		base_data = new Array(41);
		for ( i = 0; i < 41; i++ ) {
			base_data[i] = new Array(41);
		}
		enemy = new _Vector(128);
		_attack = -1;
	}

	/**
	 * ステージデータ読み込み
	 */
	function load() {
		var i, j;
		var stage_data;

		chip = 1;
		line = 1;
		base = 1;
		bg_image = -1;
		m.dark = false;
		switch ( m.st_index ) {
		case 0:
			base_image = IMAGE_BASE0;
			chip = 10;
			line = 2;
			base = chip * line;
			stage_data = new StageData0();
			break;
		case 1:
			base_image = IMAGE_BASE1;
			chip = 12;
			line = 2;
			base = chip * line;
			bg_image = IMAGE_BACK1;
			stage_data = new StageData1();
			break;
		case 2:
			base_image = IMAGE_BASE2;
			m.dark = true;
			chip = 12;
			line = 2;
			base = chip * line;
			stage_data = new StageData2();
			break;
		case 3:
			base_image = IMAGE_BASE3;
			chip = 7;
			line = 1;
			base = chip * line;
			stage_data = new StageData3();
			break;
		case 4:
			base_image = IMAGE_BASE4;
			chip = 13;
			line = 2;
			base = chip * line;
			stage_data = new StageData4();
			break;
		case 5:
			base_image = IMAGE_BASE5;
			chip = 12;
			line = 10;
			base = chip * line;
			bg_image = IMAGE_BACK5;
			stage_data = new StageData5();
			break;
		}

		for ( i = 0; i < 40; i++ ) {
			for ( j = 0; j < 40; j++ ) {
				base_data[j][i] = stage_data.MAP[i][j];
			}
		}

		enemy.removeAllElements();
		enemy_size = 0;
		var val = new Array(7);
		for ( j = 0; ; j++ ) {
			for ( i = 0; i < 7; i++ ) {
				val[i] = stage_data.ENEMY[j][i];
			}
			if ( val[0] == E_END ) {
				break;
			}
			val[1] *= 24;
			val[2] *= 24;
			if ( val[6] < 10 ) val[6] *= 30;
			switch ( val[0] ) {
			case E_ALL:
				if ( _MOD(m.level, 2) == 1 ) {
					if ( val[3] < 4 ) {
						val[4] = _DIV(val[4] * 2, 3);
					} else {
						val[4] = _DIV(val[4], 2);
					}
					val[5] %= val[4];
				}
				enemy.addElement(new Enemy(m, val[1], val[2], val[3], val[4], val[5], val[6]));
				break;
			case E_EASY:
				if ( _MOD(m.level, 2) == 0 ) {
					enemy.addElement(new Enemy(m, val[1], val[2], val[3], val[4], val[5], val[6]));
				}
				break;
			case E_HARD:
				if ( _MOD(m.level, 2) == 1 ) {
					enemy.addElement(new Enemy(m, val[1], val[2], val[3], val[4], val[5], val[6]));
				}
				break;
			}
		}
		enemy_size = enemy.size();
	}

	/**
	 * ステージデータ構築
	 */
	function create() {
		// ステージデータ読み込み
		if ( m.st_index > 5 ) {
			// これ以上ステージが無いので最初に戻る
			m.new_level();
		}
		load();

		// 自機イメージ読み込み
		m.jiki_load_image();

		attack_x = -1;
		pattern = 0;
	}

	/**
	 * ステージデータ更新
	 */
	function update(stage_clear) {
		var i;
		var tmp;
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			tmp.update(stage_clear);
		}

		if ( !stage_clear ) {
			pattern++; if ( pattern > 1 ) pattern = 0;
		}
	}

	/**
	 * 自機の敵への攻撃
	 */
	function attack() {
		if ( m.t_damage >= m.m_damage ) return;
		var i, j;
		var jx = m.jiki_x + 12;
		var jy = m.jiki_y + 12;
		var ex, ey;
		var tmp;
		j = -1;
		if ( (m.level < 4) || (m.level > 5) ) {
			var w;
			var h;
			var dist = 96 * 96;
			var tmp_d;
			for ( i = enemy_size - 1; i >= 0; i-- ) {
				tmp = enemy.elementAt(i);
				if ( tmp._damage < tmp.m_damage ) {
					ex = tmp._x + 12;
					ey = tmp._y + 12;
					w = jx - ex;
					h = jy - ey;
					tmp_d = w * w + h * h;
					if ( tmp_d <= dist ) {
						if ( !kabe12l(_DIV(ex, 12), _DIV(ey, 12), _DIV(jx, 12), _DIV(jy, 12)) ) {
							j = i;
							dist = tmp_d;
						}
					}
				}
			}
			if ( j >= 0 ) {
				tmp = enemy.elementAt(j);
				if ( m.level < 4 ) {
					m.setCMYColor(_MOD(m._elapse, 3));
				} else {
					if ( dist <= 32 * 32 ) {
						g.setColor(COLOR_W);
					} else if ( dist <= 64 * 64 ) {
						g.setColor(COLOR_Y);
					} else {
						g.setColor(COLOR_M);
					}
				}
				attack_x = tmp._x + 12 + m.rand.next(9);
				attack_y = tmp._y + 12 + m.rand.next(9);
				if ( attack_x >= 0 ) {
					if ( m.boost ) {
						attack_x1 = jx       + _DIV(attack_x - jx, 3) + m.rand.next(9);
						attack_y1 = jy       + _DIV(attack_y - jy, 3) + m.rand.next(9);
						attack_x2 = attack_x - _DIV(attack_x - jx, 3) + m.rand.next(9);
						attack_y2 = attack_y - _DIV(attack_y - jy, 3) + m.rand.next(9);
						m.drawLine(jx, jy, attack_x1, attack_y1);
						m.drawLine(attack_x1, attack_y1, attack_x2, attack_y2);
						m.drawLine(attack_x2, attack_y2, attack_x, attack_y);
					} else {
						m.drawLine(jx, jy, attack_x, attack_y);
					}
				}
				if ( m.level < 4 ) {
//					tmp.damage(m.boost ? 2 : 1);
					tmp._damage += (m.boost ? 2 : 1); if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
				} else {
					if ( dist <= 32 * 32 ) {
//						tmp.damage(m.boost ? 6 : 3);
						tmp._damage += (m.boost ? 6 : 3); if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
					} else if ( dist <= 64 * 64 ) {
//						tmp.damage(m.boost ? 4 : 2);
						tmp._damage += (m.boost ? 4 : 2); if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
					} else {
//						tmp.damage(m.boost ? 2 : 1);
						tmp._damage += (m.boost ? 2 : 1); if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
					}
				}
				if ( tmp._damage >= tmp.m_damage ) m.add_score(tmp.m_damage * 10);
			}
		} else {
			if ( m.boost ) {
				for ( i = enemy_size - 1; i >= 0; i-- ) {
					tmp = enemy.elementAt(i);
					if ( (tmp._damage < tmp.m_damage) && tmp._show ) {
						ex = tmp._x + 12;
						ey = tmp._y + 12;
						if ( !kabe12l(_DIV(ex, 12), _DIV(ey, 12), _DIV(jx, 12), _DIV(jy, 12)) ) {
							m.setCMYColor(_MOD(m._elapse, 3));
							attack_x = m.rand.next(9);
							attack_y = m.rand.next(9);
							m.drawLine(jx, jy, tmp._x + 12 + attack_x, tmp._y + 12 + attack_y);
//							tmp.damage(1);
							tmp._damage += 1; if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
							if ( tmp._damage >= tmp.m_damage ) m.add_score(tmp.m_damage * 10);
						}
					}
				}
			} else {
				var k;
				for ( k = 0; k < 2; k++ ) {
					for ( i = _attack + 1; i < enemy_size; i++ ) {
						tmp = enemy.elementAt(i);
						if ( (tmp._damage < tmp.m_damage) && tmp._show ) {
							ex = tmp._x + 12;
							ey = tmp._y + 12;
							if ( !kabe12l(_DIV(ex, 12), _DIV(ey, 12), _DIV(jx, 12), _DIV(jy, 12)) ) {
								j = i;
								break;
							}
						}
					}
					if ( j >= 0 ) {
						_attack = j;
						break;
					}
					_attack = -1;
				}
				if ( j >= 0 ) {
					tmp = enemy.elementAt(j);
					m.setCMYColor(_MOD(m._elapse, 3));
					attack_x = m.rand.next(9);
					attack_y = m.rand.next(9);
					m.drawLine(jx, jy, tmp._x + 12 + attack_x, tmp._y + 12 + attack_y);
//					tmp.damage(1);
					tmp._damage += 1; if ( tmp._damage >= tmp.m_damage ) tmp._elapse = 0;
					if ( tmp._damage >= tmp.m_damage ) m.add_score(tmp.m_damage * 10);
				}
			}
		}
	}

	/**
	 * 敵が全滅したかどうかチェック
	 */
	function destroyed() {
		var i;
		var tmp;
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( (tmp._type == ENEMY_0) && (tmp._damage < tmp.m_damage) ) return false;
		}
		return true;
	}

	/**
	 * 当たり判定
	 */
	function hit(x, y) {
		if ( (x < 0) || (x > 936) || (y < 0) || (y > 936) ) return BASE_KABE;
		var x2 = _DIV(x + 12, 24);
		var y2 = _DIV(y + 12, 24);
		var x3 = _DIV(x, 24);
		var y3 = _DIV(y, 24);
		var x4 = x3 + 1;
		var y4 = y3 + 1;
		var slow = false;

		// 敵との当たり判定
		var i;
		var tmp;
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( tmp._damage >= tmp.m_damage ) {
				if ( (tmp._type == ENEMY_0) || (tmp._type == ENEMY_4) ) {
					if ( (_DIV(tmp._x, 24) == x2) && (_DIV(tmp._y, 24) == y2) ) slow = true;
				}
			} else if ( (x != tmp._x) || (y != tmp._y) ) {
				if ( (Math.abs(tmp._x - x) < 24) && (Math.abs(tmp._y - y) < 24) ) return BASE_KABE;
			}
		}

		// 自機との当たり判定
		if ( (x != m.jiki_x) || (y != m.jiki_y) ) {
			if ( (Math.abs(m.jiki_x - x) < 24) && (Math.abs(m.jiki_y - y) < 24) ) return BASE_KABE;
		}

		// ベースとの当たり判定
		if ( (_MOD(x, 24) != 0) && (_MOD(y, 24) != 0) ) {
			if ( _DIV(base_data[x3][y3], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x3][y4], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x4][y3], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x4][y4], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x3][y3], base) == BASE_GUARDRAIL ) return BASE_KABE;
			if ( _DIV(base_data[x3][y4], base) == BASE_GUARDRAIL ) return BASE_KABE;
			if ( _DIV(base_data[x4][y3], base) == BASE_GUARDRAIL ) return BASE_KABE;
			if ( _DIV(base_data[x4][y4], base) == BASE_GUARDRAIL ) return BASE_KABE;
		} else if ( _MOD(x, 24) != 0 ) {
			if ( _DIV(base_data[x3][y3], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x4][y3], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x3][y3], base) == BASE_GUARDRAIL ) return BASE_KABE;
			if ( _DIV(base_data[x4][y3], base) == BASE_GUARDRAIL ) return BASE_KABE;
		} else if ( _MOD(y, 24) != 0 ) {
			if ( _DIV(base_data[x3][y3], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x3][y4], base) == BASE_KABE      ) return BASE_KABE;
			if ( _DIV(base_data[x3][y3], base) == BASE_GUARDRAIL ) return BASE_KABE;
			if ( _DIV(base_data[x3][y4], base) == BASE_GUARDRAIL ) return BASE_KABE;
		}
		return slow ? BASE_SLOW : _DIV(base_data[x2][y2], base);
	}

	/**
	 * 槍との当たり判定
	 */
	function spear() {
		var i;
		var tmp;
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( (tmp._damage < tmp.m_damage) && (tmp._type == ENEMY_6) ) {
				if (
				(tmp._sx >= m.jiki_x     ) &&
				(tmp._sx <  m.jiki_x + 24) &&
				(tmp._sy >= m.jiki_y     ) &&
				(tmp._sy <  m.jiki_y + 24)
				) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 指定位置が壁かどうかチェック(注意：画面外チェックは行っていない)
	 */
//	function kabe12p(x, y) {
//		if ( _DIV(base_data[_DIV(x, 2)][_DIV(y, 2)], base) == BASE_KABE ) return true;
//		return false;
//	}

	/**
	 * 直線が壁に遮られているかチェック(注意：画面外チェックは行っていない)
	 */
	function kabe12l(x0, y0, x1, y1) {
		var i;
		var e, x, y;
		var dx, dy, sx, sy;
		sx = (x1 > x0) ? 1 : -1;
		dx = (x1 > x0) ? x1 - x0 : x0 - x1;
		sy = (y1 > y0) ? 1 : -1;
		dy = (y1 > y0) ? y1 - y0 : y0 - y1;
		x = x0;
		y = y0;
		if ( dx >= dy ) {
			e = -dx;
			for ( i = 0; i <= dx; i++ ) {
				if ( _DIV(base_data[_DIV(x, 2)][_DIV(y, 2)], base) == BASE_KABE ) return true;
				x += sx;
				e += 2 * dy;
				if ( e >= 0 ) {
					y += sy;
					e -= 2 * dx;
				}
			}
		} else {
			e = -dy;
			for ( i = 0; i <= dy; i++ ) {
				if ( _DIV(base_data[_DIV(x, 2)][_DIV(y, 2)], base) == BASE_KABE ) return true;
				y += sy;
				e += 2 * dx;
				if ( e >= 0 ) {
					x += sx;
					e -= 2 * dy;
				}
			}
		}
		return false;
	}

	/**
	 * 爆発
	 */
	function baku(x, y, w, elapse) {
		var i;
		i =  _DIV(elapse, BAKU_FRAME); if ( (i >= 0) && (i < 5) ) m.drawScaledImage(IMAGE_BAKU, x + i * 2, y + i * 2, 24 - i * 4, 24 - i * 4);
		if ( w > 26 ) {
			if ( i == 0 ) m.quake = 15;
			i = _DIV(elapse - BAKU_LAG1, BAKU_FRAME); if ( (i >= 0) && (i < 5) ) m.drawScaledImage(IMAGE_BAKU, x - 6 + i * 2, y - 6 + i * 2, 24 - i * 4, 24 - i * 4);
			i = _DIV(elapse - BAKU_LAG2, BAKU_FRAME); if ( (i >= 0) && (i < 5) ) m.drawScaledImage(IMAGE_BAKU, x + 6 + i * 2, y - 2 + i * 2, 24 - i * 4, 24 - i * 4);
			i = _DIV(elapse - BAKU_LAG3, BAKU_FRAME); if ( (i >= 0) && (i < 5) ) m.drawScaledImage(IMAGE_BAKU, x + 2 + i * 2, y + 6 + i * 2, 24 - i * 4, 24 - i * 4);
		}
	}

	/**
	 * 描画
	 */
	function draw(title) {
		var i, j, x, y, w, h;
		var y2, y3;
		var qx, qy;

		m._win_x = m.jiki_x - 96;
		m._win_y = m.jiki_y - 96;
		if ( m._win_x < 0 ) {
			m._win_x = 0;
		} else if ( m._win_x + 216 > 960 ) {
			m._win_x = 960 - 216;
		}
		if ( m._win_y < 0 ) {
			m._win_y = 0;
		} else if ( m._win_y + 216 > 960 ) {
			m._win_y = 960 - 216;
		}

		if ( !title && m.dark ) {
			m.setClip(m._light_x - m._win_x, m._light_y - m._win_y, 120, 120);
		}
		if ( m.quake > 0 ) {
			qx = m.quake_x;
			qy = m.quake_y;
			m.setOrigin(12 + qx, 12 + qy);
		} else {
			qx = 0;
			qy = 0;
		}
		if ( bg_image >= 0 ) {
			// 背景の描画
			x = _DIV(m._win_x, 3);
			y = _DIV(m._win_y, 3);
			w = 240 - x;
			h = 240 - y;
			if ( w > 0 && h > 0 ) { g.drawScaledImage(bg_image, -x + m.origin_x, -y + m.origin_y, 240, 240); }
			if ( x > 0 && h > 0 ) { g.drawScaledImage(bg_image,  w + m.origin_x, -y + m.origin_y, 240, 240); }
			if ( w > 0 && y > 0 ) { g.drawScaledImage(bg_image, -x + m.origin_x,  h + m.origin_y, 240, 240); }
			if ( x > 0 && y > 0 ) { g.drawScaledImage(bg_image,  w + m.origin_x,  h + m.origin_y, 240, 240); }
		}
		m.drawScaledImage(base_image, 0, 0, 960, 960);
		if ( m.quake > 0 ) {
			m.setOrigin(12, 12);
		}

		if ( title ) {
			return;
		}

		var tmp;
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( tmp._damage >= tmp.m_damage ) {
				if ( (tmp._type == ENEMY_0) || (tmp._type == ENEMY_4) ) {
					m.drawImage(IMAGE_ENEMY_03, tmp._x - 4 + qx, tmp._y - 4 + qy, 32, 32);
				}
			} else {
				switch ( tmp._type ) {
				case ENEMY_0:
					if ( tmp._attack == RING_RANDOM ) {
						tmp._show = m.drawImage(IMAGE_ENEMY_00 + _MOD(m._elapse, 3), tmp._x + qx, tmp._y + qy, 32, 32);
					} else {
						tmp._show = m.drawImage(IMAGE_ENEMY_00 + tmp._attack, tmp._x + qx, tmp._y + qy, 32, 32);
					}
					break;
				case ENEMY_4:
					tmp._show = m.drawImage(IMAGE_ENEMY_40 + _MOD(m._elapse, 3), tmp._x - 4 + qx, tmp._y - 4 + qy, tmp._w, tmp._w);
					break;
				case ENEMY_1:
					tmp._show = m.drawImage(IMAGE_ENEMY_10 + pattern * 2 + _DIV(tmp._pattern, 4), tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				case ENEMY_2:
					tmp._show = m.drawImage(IMAGE_ENEMY_20 + pattern * 5 + tmp._pattern, tmp._x - 4, tmp._y - 4, tmp._w, tmp._w);
					break;
				case ENEMY_3:
					tmp._show = m.drawImage(IMAGE_ENEMY_30 + pattern * 5 + tmp._pattern, tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				case ENEMY_5:
					tmp._show = m.drawImage(IMAGE_ENEMY_50, tmp._x - 4, tmp._y - 4, tmp._w, tmp._w);
					break;
				case ENEMY_6:
					tmp._show = m.drawImage(IMAGE_ENEMY_60, tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				}
			}
		}
		if ( m.dark ) {
			m.drawScaledImage(IMAGE_LIGHT, m._light_x - 200, m._light_y - 200, 520, 520);
			m.setClip(0, 0, 216, 216);
		}
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( tmp._damage >= tmp.m_damage ) {
				baku(tmp._x, tmp._y, tmp._w, tmp._elapse);
			} else if ( m.dark ) {
				switch ( tmp._type ) {
				case ENEMY_0:
					if ( tmp._attack == RING_RANDOM ) {
						tmp._show = m.drawImage(IMAGE_ENEMYD_00 + _MOD(m._elapse, 3), tmp._x + qx, tmp._y + qy, 32, 32);
					} else {
						tmp._show = m.drawImage(IMAGE_ENEMYD_00 + tmp._attack, tmp._x + qx, tmp._y + qy, 32, 32);
					}
					break;
				case ENEMY_4:
					tmp._show = m.drawImage(IMAGE_ENEMYD_40 + _MOD(m._elapse, 3), tmp._x - 4 + qx, tmp._y - 4 + qy, tmp._w, tmp._w);
					break;
				case ENEMY_1:
					tmp._show = m.drawImage(IMAGE_ENEMYD_10 + _DIV(tmp._pattern, 4), tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				case ENEMY_2:
					tmp._show = m.drawImage(IMAGE_ENEMYD_20, tmp._x - 4, tmp._y - 4, tmp._w, tmp._w);
					break;
				case ENEMY_3:
					tmp._show = m.drawImage(IMAGE_ENEMYD_30 + tmp._pattern, tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				case ENEMY_5:
					tmp._show = m.drawImage(IMAGE_ENEMYD_50, tmp._x - 4, tmp._y - 4, tmp._w, tmp._w);
					break;
				case ENEMY_6:
					tmp._show = m.drawImage(IMAGE_ENEMYD_60, tmp._x, tmp._y, tmp._w, tmp._w);
					break;
				}
			}
		}
		m.setCMYColor(_MOD(m._elapse, 3));
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( (tmp._damage < tmp.m_damage) && (tmp._type == ENEMY_6) && tmp._show ) {
				m.drawLine(
					tmp._x + 12, tmp._y + 12,
					tmp._sx, tmp._sy
					);
			}
		}
	}

	/**
	 * マップ描画
	 */
	function draw_map(x, y) {
		var i;
		var tmp;
		g.setColor(COLOR_W);
		g.drawRect(x, y, 63, 63);
		x += 2;
		y += 2;
		g.drawRect(x + _DIV(m.jiki_x, 16), y + _DIV(m.jiki_y, 16), 1, 1);
		m.setCMYColor(_MOD(m._elapse, 3));
		for ( i = enemy_size - 1; i >= 0; i-- ) {
			tmp = enemy.elementAt(i);
			if ( (tmp._type == ENEMY_0) && (tmp._damage < tmp.m_damage) ) {
				g.drawRect(x + _DIV(tmp._x, 16), y + _DIV(tmp._y, 16), 1, 1);
			}
		}
	}
}
