private static void WriteResultIPs(VLSM__RESULT item)
 {
     Guides += $"{Environment.NewLine}";
     Guides += $@"             ——> Net address     : {item.NetAddress.DecimalStringValue}{Environment.NewLine}";
     Guides += $@"             ——> First IP              : {item.FirstIP.DecimalStringValue}{Environment.NewLine}";
     Guides += $@"             ——> Last IP              : {item.LastIP.DecimalStringValue}{Environment.NewLine}";
     Guides += $@"             ——> BroadCast IP    : {item.BroadCastIP.DecimalStringValue}{Environment.NewLine}";
 }
        private static VLSM__RESULT GetResult(List <IPv4> listSubnets, Branch currBranch)
        {
            //  item kết quả
            VLSM__RESULT result = null;



            //  Lấy ra IP cuối cùng để xét (IP cuối cùng là đường mạng đầu tiên được chia)
            IPv4 currIP = listSubnets.Last();


            //  Lấy các đơn vị (số mạng con, bước nhảy, ...)
            VLSM_Units vlsm_units = GetVLSM_Units(currBranch, currIP);



            Guides += $@"       ——>  Net address:   {currIP.ToDecimalString()}/{currIP.Suffix}{Environment.NewLine}";
            Guides += $@"       ——>  2^h - 2 >= {currBranch.HostsAmount}  ——>  h = {vlsm_units.AfterHosts} (remainder bits of the host ID after borrowed){Environment.NewLine}";
            Guides += $@"       ——>  m = {vlsm_units.BorrowedBitsAmount} (the borrowed bits){Environment.NewLine}";
            if (vlsm_units.BorrowedBitsAmount > 0)
            {
                Guides += $@"       ——>  subnets amount:  2^m  =  2^{vlsm_units.BorrowedBitsAmount}  =  {vlsm_units.SubnetsAmount}{Environment.NewLine}";
                Guides += $@"       ——>  hop:  2^h  =  2^{vlsm_units.AfterHosts}  =  {vlsm_units.Hop}{Environment.NewLine}";
            }



            if (vlsm_units.BorrowedBitsAmount == 0)      //  Không mượn bit ==> chọn ngay đường mạng hiện tại
            {
                Guides += $@"{Environment.NewLine}       Because the borrowed bits (m) is equals to 0, so we'll directly pick up the current Net address without dividing !";
                WriteHostFormat(currIP, vlsm_units);


                //  Lấy item kết quả
                result = GetVLSM_Result_Item(currIP, currBranch, vlsm_units);
                WriteResultIPs(result);


                //  Xoá đi phần tử vừa chọn
                listSubnets.Remove(currIP);
            }
            else                                    //  Có mượn bit ==> phải chia tiếp
            {
                result = DivideNewSubnets(vlsm_units, listSubnets, currBranch);
            }



            return(result);
        }
        private static VLSM__RESULT GetVLSM_Result_Item(IPv4 ip, Branch brch, VLSM_Units vlsm_units)
        {
            VLSM__RESULT item = new VLSM__RESULT();

            item.Branch      = brch;
            item.IPArea      = ip.GetIPRange(vlsm_units);
            item.NetAddress  = item.IPArea.First();
            item.BroadCastIP = item.IPArea.Last();
            item.FirstIP     = item.IPArea[1];
            item.LastIP      = item.IPArea[2];
            item.SubnetMask  = ip.SubnetMask;


            return(item);
        }
        public static List <VLSM__RESULT> GetQuickResult(List <VLSM.Branch> listBranches, VLSM.IPv4 rootIP)
        {
            branchesAmount = listBranches.Count;
            WriteInput(listBranches, rootIP);



            //  Sắp xếp danh sách các chi nhánh giảm dần theo số Hosts
            Branch.SortDescendantByHostsAmount(listBranches);


            //  List các mạng con được sinh ra
            List <IPv4> listSubnets = new List <VLSM.IPv4>();

            listSubnets.Add(rootIP);


            //  List kết quả
            List <VLSM__RESULT> listResult = new List <VLSM__RESULT>();



            //  Duyệt từng chi nhánh từ đầu đến cuối (host giảm dần)
            foreach (VLSM.Branch branch in listBranches)
            {
                Guides += $@"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}
————————————————————————————————————————————————————————————{Environment.NewLine}";
                Guides += $@">>>  {branch.Name} ({branch.HostsAmount}){Environment.NewLine}{Environment.NewLine}";


                //  Thêm một item kết quả
                VLSM__RESULT item = GetResult(listSubnets, branch);


                if (item == null)
                {
                    return(null);
                }


                listResult.Add(item);
            }


            return(listResult);
        }
        private static VLSM__RESULT DivideNewSubnets(VLSM_Units vlsm_units, List <IPv4> listSubnets, Branch currBranch)
        {
            //  Lấy ra IP cuối cùng (đường mạng tiếp theo) để chia
            IPv4 currIP = listSubnets.Last();

            WriteNetAddressFormat(currIP, vlsm_units);
            Guides += Environment.NewLine;



            //  Các bit đã mượn để bật bit thành các đường mạng
            BinaryNumber borrowedBits = new BinaryNumber(bitsAmount: vlsm_units.BorrowedBitsAmount);


            //List các đường mạng con được sinh ra khi bật bit
            List <IPv4> listNewSubnets = new List <IPv4>();



            //  Xác định index của bit mượn đầu tiên trong IP (bắt đầu từ 1)
            int startBorrowingBitIndex = 32 - vlsm_units.BeforeHosts + 1;


            //  List các bit của IP hiện tại
            List <int> listCurrBits = currIP.ToBinaryList();


            //  Bật các bit mượn lên IP hiện tại để tính ra các đường mạng con
            for (int i = 0; i < vlsm_units.SubnetsAmount; ++i)
            {
                int assignedCounter = 0;
                for (int j = 0; j < 32; ++j)
                {
                    if (j + 1 >= startBorrowingBitIndex)
                    {
                        listCurrBits[j] = borrowedBits.ListBits[assignedCounter++];
                    }


                    if (assignedCounter == borrowedBits.ListBits.Count)
                    {
                        break;
                    }
                }



                //  Thêm mạng con mới vào list tạm thời
                listNewSubnets.Add(new IPv4(listCurrBits, currIP.Suffix + vlsm_units.BorrowedBitsAmount));
                Guides += $@"           M{listNewSubnets.Count}:    {listNewSubnets.Last().DecimalStringValue}";
                Guides += Environment.NewLine;


                //  Bật bit
                borrowedBits.Increase();



                //  Dừng lấy thêm đường mạng khi đã đủ
                if (listNewSubnets.Count == branchesAmount)
                {
                    if (branchesAmount < vlsm_units.SubnetsAmount)
                    {
                        Guides += $@"              ...{Environment.NewLine}";
                    }

                    break;
                }
            }


            if (listNewSubnets.Count == 0)
            {
                System.Windows.Forms.MessageBox.Show($"An error just occured!  Don't enough HOST BITS to divide new subnets for {currBranch.Name}",
                                                     "Alert", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);

                return(null);
            }
            else
            {
                //  Xoá phần tử đã được chia
                listSubnets.Remove(currIP);

                //  Đảo ngược thứ tự của các phần tử mới
                listNewSubnets.Reverse();

                //  Thêm các phần tử mới vào list
                listSubnets.AddRange(listNewSubnets);

                //  Chọn phần tử cuối cùng (tương đương với mạng con thứ nhất mới được chia)
                currIP = listSubnets.Last();

                //  Xoá phần tử được chọn
                listSubnets.Remove(currIP);
            }



            VLSM__RESULT result = listNewSubnets.Count == 0 ? null : GetVLSM_Result_Item(currIP, currBranch, vlsm_units);

            if (result != null)
            {
                Guides += $@"{Environment.NewLine}       Select M1 to apply:";
                WriteHostFormat(currIP, vlsm_units);
                WriteResultIPs(result);
            }



            //  Trả về item kết quả
            return(result);
        }