/// <summary>
        /// Tworzy profil nurkowania na podstawie listy segmentów
        /// </summary>
        /// <returns>Profil nurkowania czyli listę punktów na których beą przeprowadzane obliczenia</returns>
        public ProfileData GetProfileData()
        {
            ProfileData profileData    = new ProfileData();
            GasMix      currentGasMix  = gasesList.First();
            double      time           = 0;
            double      finialPreasure = 0;

            foreach (DiveSegment diveSegment in segmentsList)
            {
                if (diveSegment.GasName != currentGasMix.Name)
                {
                    currentGasMix = GetGas(diveSegment.GasName);
                }
                ProfileData.profileData newData = new ProfileData.profileData();
                newData.initialT    = time;
                newData.deltaT      = diveSegment.Time;
                newData.initialD    = diveSegment.InitialDepth;
                newData.deltaD      = diveSegment.FinialDepth - diveSegment.InitialDepth;
                newData.initialP    = PresureAtDepth(diveSegment.InitialDepth);
                finialPreasure      = PresureAtDepth(diveSegment.FinialDepth);
                newData.deltaP      = finialPreasure - newData.initialP;
                newData.initialPPN2 = newData.initialP * currentGasMix.Nitrogen;
                newData.deltaPPN2   = finialPreasure * currentGasMix.Nitrogen - newData.initialPPN2;
                newData.initialPPHe = newData.initialP * currentGasMix.Helium;
                newData.deltaPPHe   = finialPreasure * currentGasMix.Helium - newData.initialPPHe;
                newData.initialPPO2 = newData.initialP * currentGasMix.Oxygen;
                newData.deltaPPO2   = finialPreasure * currentGasMix.Oxygen - newData.initialPPO2;
                profileData.Add(newData);
                time += diveSegment.Time;
            }
            return(profileData);
        }
 /// <summary>
 /// EAD - Eqivalent Air Depth - równoważna głębokość powietrzna
 /// </summary>
 /// <param name="gas">Mieszanka oddechowa</param>
 /// <param name="depth">Głębokość</param>
 /// <returns>Zwraca głebokość przy której cisnienie parcjalne azotu dla powietrza byłoby identyczne z ciśnieniem parcjalne azotu w mieszance dla zadanej głębokości</returns>
 /// <exception cref="System.Exception">Dla TMX jest wyrzuacany wyjątek</exception>
 public double EAD(GasMix gas, double depth)
 {
     if (gas.Helium > Double.Epsilon)
     {
         throw new Exception("EAD is not available for TMX");
     }
     return(END(gas, 0.0));
 }
        /// <summary>
        /// EDD - Eqivalent Dencity Depth - równoważna głębokość gęstościowa
        /// </summary>
        /// <param name="gas">Mieszanka oddechowa</param>
        /// <param name="depth">Głębokość</param>
        /// <returns>Zwraca głebokość przy której gęstość powietrza byłaby identyczna z gęstością mieszanki dla zadanej głębokości</returns>
        public double EDD(GasMix gas, double depth)
        {
            double edd = depth;

            if (gas.Helium > Double.Epsilon || !Double.Equals(gas.Oxygen, Utility.densityOxygen))
            {
                double airDencity = Utility.airOxigenContent * Utility.densityOxygen + (1.0 - Utility.airOxigenContent) * Utility.densityNitrogen;
                double gasDencity = gas.Oxygen * Utility.densityOxygen + gas.Nitrogen * Utility.densityNitrogen + gas.Helium * Utility.densityHelium;
                edd = DepthAtPresure((airDencity / gasDencity) * PresureAtDepth(depth));
            }
            return(edd);
        }
        /// <summary>
        /// END - Eqivalent Narcotic Depth - równoważna głębokość narkotyczna
        /// </summary>
        /// <param name="gas">Mieszanka oddechowa</param>
        /// <param name="depth">Głębokość</param>
        /// <param name="narcoticOxigenToNitrogen">Narkotycznośc tlenu w odniesieniu do azotu 0.0 - brak, 1.0 (wartość domyślna) tlen tak samo narkotyczny jak azot</param>
        /// <returns></returns>
        public double END(GasMix gas, double depth, double narcoticOxigenToNitrogen = 1.0)
        {
            double end = depth;

            if (gas.Helium > Double.Epsilon || !Double.Equals(narcoticOxigenToNitrogen, 1.0))
            {
                double airNarcotic = Utility.airOxigenContent * narcoticOxigenToNitrogen + (1.0 - Utility.airOxigenContent);
                double gasNarcotic = gas.Oxygen * narcoticOxigenToNitrogen + gas.Nitrogen;
                end = DepthAtPresure(airNarcotic / gasNarcotic * PresureAtDepth(depth));
            }
            return(end);
        }
        /// <summary>
        /// Usówa gaz z listy gazów
        /// </summary>
        /// <param name="gasName">Mieszanka gazów do usunięcia</param>
        /// <returns>true - gazy został usunięty, false - gaz do usunięcia nie istniał dla tego nurkowania</returns>
        public bool RemoveGas(string gasName)
        {
            GasMix gas = GetGas(gasName);

            if (gas != null)
            {
                return(RemoveGas(gas));
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Zamienia gaz na liśie gazów
        /// </summary>
        /// <param name="newGas">Nowa mieszanka gazów</param>
        /// <param name="oldGas">Mieszanka gazów do usunięcia</param>
        /// <returns>true - gazy zostały zamienione, false - gaz do usunięcia nie istniał dla tego nurkowania</returns>
        public bool ReplaceGas(GasMix newGas, GasMix oldGas)
        {
            int i = gasesList.IndexOf(oldGas);

            if (i < 0)
            {
                return(false);
            }
            else
            {
                gasesList[i] = newGas;
                return(true);
            }
        }
        /// <summary>
        /// Dodaje mieszankę do listy mieszanek gazów
        /// </summary>
        /// <param name="gas">Mieszanka gazów</param>
        /// <returns>true - gaz został dodany, false - gaz o tej nazwie juz istnieje dla tego nurkowania</returns>
        public bool AddGas(GasMix gas)
        {
            GasMix g = GetGas(gas.Name);

            if (g == null)
            {
                gasesList.Add(gas);
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Zwraca mieszankę gazów na podstwie nazwy
        /// </summary>
        /// <param name="gasName">Nazwa mieszanki</param>
        /// <returns>Zwraca mieszankę gazów, lub null gdy nie istnieje taka mieszanka</returns>
        public GasMix GetGas(string gasName)
        {
            GasMix gas = null;

            try
            {
                gas = gasesList.Find(
                    delegate(GasMix g)
                {
                    return(g.Name == gasName);
                }
                    );
            }
            catch (Exception e) { };

            return(gas);
        }
        /// <summary>
        /// Modyfikuje dane segmentu
        /// </summary>
        /// <param name="segmentName">Nazwa(identyfikator) segmentu</param>
        /// <param name="initialDepth">Głębokość poczatkowa [m]</param>
        /// <param name="finialDepth">Głębokość końcowa [m]</param>
        /// <param name="segmentTime">Czas trwania segmentu [min]</param>
        /// <param name="gas">Gaz w obrębie segmentu</param>
        /// <returns>Zwraca nazwę(identyfikator) segmentu po zmianie parametrów</returns>
        /// <exception cref="System.Exception">W razie problemów jest wyrzuacany wyjątek</exception>
        public string ChangeSegment(string segmentName, double initialDepth, double finialDepth, double segmentTime, GasMix gas = null)
        {
            string newName       = segmentName;
            bool   intDepthChage = false;
            bool   finDepthChage = false;

            try
            {
                int index = segmentsList.FindIndex(s => s.Name == segmentName);
                segmentsList[index].Time = segmentTime;
                segmentsList[index].setDefaultName();
                newName       = segmentsList[index].Name;
                intDepthChage = (Math.Abs(segmentsList[index].InitialDepth - initialDepth) > Double.Epsilon);
                finDepthChage = (Math.Abs(segmentsList[index].FinialDepth - finialDepth) > Double.Epsilon);
                if (gas != null)
                {
                    AddGas(gas);
                    segmentsList[index].GasName = gas.Name;
                    segmentsList[index].setDefaultName();
                    newName = segmentsList[index].Name;
                }
                if (intDepthChage || finDepthChage)
                {
                    double deltaDepth = finialDepth - initialDepth;
                    if (deltaDepth > 1e-3)
                    {
                        segmentsList[index].Time = deltaDepth / DescentSpeed;
                    }
                    else if (deltaDepth < -1e-3)
                    {
                        segmentsList[index].Time = -deltaDepth / AscentSpeed;
                    }
                    segmentsList[index].InitialDepth = initialDepth;
                    segmentsList[index].FinialDepth  = finialDepth;
                    segmentsList[index].setDefaultName();
                    newName = segmentsList[index].Name;
                    RefactorSegmentsList(index, intDepthChage);
                }
            }
            catch (Exception)
            {
                throw new Exception("ChangeSegment(string segmentName, double initialDepth, double finialDepth, double segmentTime, GasMix gas = null): Invalid segment");
            }
            return(newName);
        }
 /// <summary>
 /// Usuwa gaz z listy mieszanek gazów
 /// </summary>
 /// <param name="gas">Mieszanka gazów</param>
 /// <returns>true - gaz został usunięty, false - gaz o tej nazwie nie istnieje dla tego nurkowania</returns>
 public bool RemoveGas(GasMix gas)
 {
     return(gasesList.Remove(gas));
 }