using System;

public class XOR128
{
	public XOR128(int x_)
	{
		this.x = (ulong)(471283569 + x_);
	}

	public uint next()
	{
		ulong num = this.x ^ this.x << 11;
		this.x = this.y;
		this.y = this.z;
		this.z = this.w;
		return (uint)(this.w = (this.w ^ this.w >> 19 ^ (num ^ num >> 8)));
	}

	public static byte[] DECO(byte[] bo, int seed = 555)
	{
		int num = bo.Length;
		byte[] array = new byte[num];
		XOR32 xor = new XOR32(311 + bo.Length);
		for (int i = 0; i < num - 1; i++)
		{
			array[i] = (bo[i + 1] ^ (byte)xor.next());
		}
		XOR128 xor2 = new XOR128(seed + num - 1);
		int num2 = num - 1;
		for (int j = 0; j < num2; j++)
		{
			uint num3 = (uint)((ulong)xor2.next() % (ulong)((long)num2));
			byte b = array[j];
			array[j] = array[(int)((UIntPtr)num3)];
			array[(int)((UIntPtr)num3)] = b;
		}
		XOR32 xor3 = new XOR32(seed + num - 1);
		byte[] array2 = new byte[num - 1 - 1];
		for (int k = 0; k < array2.Length; k++)
		{
			array2[k] = (array[k + 1] ^ (byte)xor3.next());
		}
		bo = null;
		return array2;
	}

	public static byte[] ENCO(byte[] b_, int seed = 555)
	{
		byte[] array = new byte[b_.Length + 1];
		XOR32 xor = new XOR32(seed + array.Length);
		array[0] = 1;
		for (int i = 0; i < b_.Length; i++)
		{
			array[i + 1] = (b_[i] ^ (byte)xor.next());
		}
		XOR128 xor2 = new XOR128(seed + array.Length);
		int num = array.Length;
		uint[] array2 = new uint[num];
		for (int j = 0; j < array.Length; j++)
		{
			array2[j] = (uint)((ulong)xor2.next() % (ulong)((long)num));
		}
		for (int k = num - 1; k >= 0; k--)
		{
			byte b = array[k];
			array[k] = array[(int)((UIntPtr)array2[k])];
			array[(int)((UIntPtr)array2[k])] = b;
		}
		byte[] array3 = new byte[array.Length + 1];
		XOR32 xor3 = new XOR32(311 + array3.Length);
		for (int l = 0; l < array.Length; l++)
		{
			array3[l + 1] = (array[l] ^ (byte)xor3.next());
		}
		array3[0] = 1;
		return array3;
	}

	private ulong x;

	private ulong y = 362436069UL;

	private ulong z = 521288629UL;

	private ulong w = 88675123UL;
}
