/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.IO;

namespace Apache.NMS.Util
{
    /// <summary>
    /// Support class that switches from one endian to the other.
    /// </summary>
    [CLSCompliant(false)]
    public class EndianSupport
    {
        public static char SwitchEndian(char x)
        {
            return (char) (
                (((char) ((byte) (x))) << 8) |
                (((char) ((byte) (x >> 8))))
            );
        }

        public static short SwitchEndian(short x)
        {
            return (short) (
                (((ushort) ((byte) (x))) << 8) |
                (((ushort) ((byte) (x >> 8))))
            );
        }

        public static int SwitchEndian(int x)
        {
            return
                (((int) ((byte) (x))) << 24) |
                (((int) ((byte) (x >> 8))) << 16) |
                (((int) ((byte) (x >> 16))) << 8) |
                (((int) ((byte) (x >> 24))));
        }

        public static long SwitchEndian(long x)
        {
            return
                (((long) ((byte) (x))) << 56) |
                (((long) ((byte) (x >> 8))) << 48) |
                (((long) ((byte) (x >> 16))) << 40) |
                (((long) ((byte) (x >> 24))) << 32) |
                (((long) ((byte) (x >> 32))) << 24) |
                (((long) ((byte) (x >> 40))) << 16) |
                (((long) ((byte) (x >> 48))) << 8) |
                (((long) ((byte) (x >> 56))));
        }

        public static ushort SwitchEndian(ushort x)
        {
            return (ushort) (
                (((ushort) ((byte) (x))) << 8) |
                (((ushort) ((byte) (x >> 8))))
            );
        }

        public static uint SwitchEndian(uint x)
        {
            return
                (((uint) ((byte) (x))) << 24) |
                (((uint) ((byte) (x >> 8))) << 16) |
                (((uint) ((byte) (x >> 16))) << 8) |
                (((uint) ((byte) (x >> 24))));
        }

        public static ulong SwitchEndian(ulong x)
        {
            return
                (((ulong) ((byte) (x))) << 56) |
                (((ulong) ((byte) (x >> 8))) << 48) |
                (((ulong) ((byte) (x >> 16))) << 40) |
                (((ulong) ((byte) (x >> 24))) << 32) |
                (((ulong) ((byte) (x >> 32))) << 24) |
                (((ulong) ((byte) (x >> 40))) << 16) |
                (((ulong) ((byte) (x >> 48))) << 8) |
                (((ulong) ((byte) (x >> 56))));
        }

        public static double SwitchEndian(double x)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write(x);
            bw.Flush();
            ms = new MemoryStream(SwitchEndian(ms.ToArray()));
            BinaryReader br = new BinaryReader(ms);
            return br.ReadDouble();
        }


        public static float SwitchEndian(float x)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write(x);
            bw.Flush();
            ms = new MemoryStream(SwitchEndian(ms.ToArray()));
            BinaryReader br = new BinaryReader(ms);
            return br.ReadSingle();
        }


        public static byte[] SwitchEndian(byte[] x)
        {
            byte[] rc = new byte[x.Length];
            int j = x.Length - 1;
            for (int i = 0; i < x.Length; i++)
            {
                rc[i] = x[j];
                j--;
            }

            return rc;
        }
    }
}