using System;
using System.Collections;
using System.Collections.Generic;
//using System.Linq;

//using UnityEditor;
using UnityEngine;
//using UnityEngine.UI;
//using Uhity.Entities;

using URD = UnityEngine.Random;

// public class SoftBodyPointData {
	// public Vector3 targetPoint;
	// public Vector3 point, lastPoint;
	// public Vector3 veloicty;
	// public Vector3 force;
	// public List<int> link;
// }

public class SoftBodyTest : MonoBehaviour {
	
	public Transform[] a, b;
	
	public SoftBodyPointData[] current;
	
	// Start is called before the first frame update
	void Start() {
		current = Init(a);
	}
	
	private SoftBodyPointData[] Init(Transform[] t) {
		var rt = new SoftBodyPointData[t.Length];
		
		for(int i=0; i<t.Length; i++) {
			rt[i] = new SoftBodyPointData();
			rt[i].targetPoint = t[i].position;
			rt[i].point = t[i].position;
			rt[i].lastPoint = t[i].position;
			rt[i].veloicty = Vector3.zero;
			rt[i].link = new List<int>();
		}
		
		rt[0].link.Add(3);
		rt[0].link.Add(1);
		rt[1].link.Add(0);
		rt[1].link.Add(2);
		rt[2].link.Add(1);
		rt[2].link.Add(3);
		rt[3].link.Add(2);
		rt[3].link.Add(0);
		
		return rt;
	}
	
	private void SoftBodyCalcu() {
		
		Loop(UpdateCurrentPoint);
		Loop(UpdateForce);
		Loop(UpdateVelocity);
		Loop(UpdatePosition);
		Loop(UpdateRealPosition);
		
		Loop(ApplyRenderPoint);
	}
	
	private void UpdateCurrentPoint(int i) {
		current[i].targetPoint = a[i].position;
	}
	
	private void UpdateForce(int i) {
		var disp = a[i].position - current[i].lastPoint;
		current[i].force = disp * 50f - Vector3.up * 0.5f;
		
		current[i].force += -current[i].veloicty * 5f;
		
		for(int j=0; j<current[i].link.Count; j++) {
			current[i].force += current[current[i].link[j]].veloicty * 0.3f;
		}
	}
	
	private void UpdateVelocity(int i) {
		current[i].veloicty += current[i].force * Time.deltaTime;
	}
	
	private void UpdatePosition(int i) {
		current[i].point += current[i].veloicty * Time.deltaTime;
	}
	
	private void UpdateRealPosition(int i) {
		var disp = a[i].position - current[i].point;
		var change = Vector3.ClampMagnitude(disp, 0.15f);
		
		current[i].point = a[i].position - change;
		
		current[i].veloicty = (current[i].point - current[i].lastPoint) / Time.deltaTime;
		
		current[i].lastPoint = current[i].point;
	}
	
	private void ApplyRenderPoint(int i) {
		b[i].position = current[i].point;
	}
	
	private void Loop(Action<int> Process) {
		for(int i=0; i<current.Length; i++) {
			Process(i);
		}
	}
	
	
	// Update is called once per frame
	void Update() {
		SoftBodyCalcu();
	}
}
