public void removeShipFromBodyNetwork(Vessel v, xPipeLine pipeModule)
 {
     if (ships.ContainsKey(v.id.ToString()))
     {
         ships.Remove(v.id.ToString());
     }
     updateNetworks();
     clearResources(ref pipeModule);
 }
        public void setShipLoaded(xPipeLine pipeModule, bool loaded)
        {
            string id = pipeModule.vessel.id.ToString();
            if (ships.ContainsKey(id))
            {

                ships[id].loaded = loaded;

            }
        }
 public void addShipToBodyNetwork(Vessel v, xPipeLine pipeModule, bool resetVesselResources, double dt)
 {
     if (ships.ContainsKey(v.id.ToString()))
     {
         ships[v.id.ToString()].updateVessel(v, ref pipeModule);
         
     }
     else
     {
         ships[v.id.ToString()] = pipelineShip.fromVessel(v, ref pipeModule);
         updateNetworks(); //only update whole network list during add or remove
         print("new ship, add resources.");
        // getNetworkResources(ships[v.id.ToString()], ref pipeModule, dt);
     }
 }
        public void unfocusedProducitivty(xPipeLine pipeModule)
        {
            string id = pipeModule.vessel.id.ToString();
            if (ships.ContainsKey(id))
            {

                foreach (string res in ships[id].resourceSupply.Keys)
                {
                    if (ships[id].unfocusedProductivity.ContainsKey(res))
                    {
                        if (ships[id].unfocusedProductivity[res] != 0)
                        {
                            pipeModule.part.RequestResource(res, 999999999999);
                            pipeModule.part.RequestResource(res, -ships[id].resourceSupply[res]);
                            ships[id].unfocusedProductivity[res] = 0;
                        }
                    }
                }

            }
        }
        public void resetShipResources(xPipeLine pipeModule)
        {
            string id = pipeModule.vessel.id.ToString();
            if (ships.ContainsKey(id))
            {
               
                foreach(string res in ships[id].resourceSupply.Keys)
                {
                    pipeModule.part.RequestResource(res, 999999999999);
                    pipeModule.part.RequestResource(res, -ships[id].resourceSupply[res]);
                }

            }
        }
        public void setNetworkResources(pipelineShip v, ref xPipeLine pipeModule, double dt)
        {
            
            
            
           // foreach (var res in pipeModule.part.Resources.list)

            foreach(string res in pipeModule.totalDemand.Keys)
            {
                v.resourceDemand[res] = pipeModule.totalDemand[res];
            }
            foreach (string res in pipeModule.totalSupply.Keys)
            {
                v.resourceSupply[res] = pipeModule.totalSupply[res];
            }
                //double capacityScalar = res.amount;
                //print("addResource:" + capacityScalar.ToString());
                //foreach (pipelineShip px in Networks[v.networkID])
                //     if (px.resourceMaximums.ContainsKey(res.info.name) && px.id != v.id)
                //    {
                //        double deltaRes = px.resourceMaximums[res.info.name] - px.resourceAmounts[res.info.name];
                //         deltaRes = Math.Min(capacityScalar, deltaRes);
                //         px.resourceAmounts[res.info.name] += deltaRes; //distribute network resources evenly
                //      capacityScalar -= deltaRes;
                //      print("added " + deltaRes + " to go " + capacityScalar);

                //    }
                   
            //    if(v.resourceSupply.ContainsKey(res.name))
            //    {
            //        v.resourceDeltas[res.info.name] = (res.amount - v.resourceAmounts[res.info.name]) * dt;
            //        v.resourceAmounts[res.info.name] = res.amount;
                    
            //    }
            //}
            
           

        }
        public void clearResources(ref xPipeLine pipeModule)
        {

          //  pipeModule.part.Resources.list.Clear();
            string recipeOutputs = "";
            
            pipeModule.RecipeOutputs = recipeOutputs;
            pipeModule.reloadRecipe();
           

        }
        public void getNetworkResources(pipelineShip p, ref xPipeLine pipeModule, double dt)
        {
            Dictionary<string, double> supply = new Dictionary<string, double>();
            Dictionary<string, double> demand = new Dictionary<string, double>();
            Dictionary<string, double> capacity = new Dictionary<string, double>();
           // pipeModule.contributors = new Dictionary<string, Dictionary<string, double>>();

            foreach(pipelineShip px in Networks[p.networkID])
           {
               if (px.id == p.id) continue;
                foreach(string k in px.resourceSupply.Keys)
                {
                    if (k == "pipeNetwork")
                        continue;
                    if (supply.ContainsKey(k))
                    {
                        double capacityScalar = Math.Min(px.resourceCapacity[k], dt) / dt;
                        supply[k] += px.resourceSupply[k] * capacityScalar;
                        demand[k] += px.resourceDemand[k];
                        
                    }
                    else
                    {
                        double capacityScalar = Math.Min(px.resourceCapacity[k], dt) / dt;
                        supply[k] = px.resourceSupply[k] * capacityScalar;
                        demand[k] = px.resourceDemand[k];
                         
                    }
                  

                }
                
              

           }
            //pipeModule.part.Resources.list.Clear();
            //foreach (string k in amounts.Keys)
            //{
            //    ConfigNode resourceNode = new ConfigNode("RESOURCE");

            //    resourceNode.AddValue("name", k);
            //    resourceNode.AddValue("amount", amounts[k].ToString());
            //    resourceNode.AddValue("maxAmount", maximums[k].ToString());
            //    print("try to add resource...");
            //    try
            //    {
            //        var resource = pipeModule.part.AddResource(resourceNode);

            //        print("resource defined " + resource.info.name + " " + resource.amount.ToString() + " " + resource.maxAmount.ToString());
            //    }
            //    catch { }

            //}

           print("part has resources " + pipeModule.part.Resources.Count.ToString());
           foreach (var res in pipeModule.part.Resources.list)
               print("resource " + res.info.name + " " + res.amount.ToString() + " " + res.maxAmount.ToString());

           string recipeOutputs = "";
           foreach (string k in demand.Keys)
           {
               
               recipeOutputs += k + "," + ( (supply[k] - demand[k])).ToString() + ",true;";
           }
            recipeOutputs = recipeOutputs.TrimEnd(';');
            print("recipe outputs = " + recipeOutputs);

            pipeModule.RecipeOutputs = recipeOutputs;
            pipeModule.reloadRecipe();
            print("adjusting mass... resource mass = " + pipeModule.part.GetResourceMass().ToString());
           
            print("part mass..." + pipeModule.part.mass.ToString());

            p.needsResourceUpdate = false;
        }
        public  void updateVessel(Vessel v, ref xPipeLine pipe)
        {
            

            id = v.id.ToString();
            lat = v.latitude;
            name = v.RevealName();
            lon = v.longitude;
            body = v.mainBody.name;
            altitude = v.altitude;
            //var modulelist = v.FindPartModulesImplementing<xPipeLine>();
            foreach (string res in pipe.totalSupply.Keys)
            {
                resourceSupply[res] = pipe.totalSupply[res];
                resourceDemand[res] = pipe.totalDemand[res];
                resourceCapacity[res] = pipe.totalCapacity[res];  //don't touch the unfocused productivity
            }
            foreach(string res in pipe.networkDelta.Keys)
                networkDraw[res] = pipe.networkDelta[res];
            loaded = v.loaded;

            debug();
           // resourceSupply = new Dictionary<string, double>();
          //  resourceDemand = new Dictionary<string, double>();
           // ret.resourceCapacity = new Dictionary<string, double>();
            
        }
        public static pipelineShip fromVessel(Vessel v, ref xPipeLine pipe)
        {
            pipelineShip ret = new pipelineShip();

            ret.id = v.id.ToString();
            ret.lat = v.latitude;
            ret.lon = v.longitude;
            ret.name = v.RevealName() ;
            ret.body = v.mainBody.name;
            ret.altitude = v.altitude;
            var modulelist =  v.FindPartModulesImplementing<xPipeLine>();
            ret.resourceSupply = new Dictionary<string, double>();
            ret.resourceDemand = new Dictionary<string, double>();
            ret.resourceCapacity = new Dictionary<string, double>();
            ret.unfocusedProductivity = new Dictionary<string, double>();
            ret.loaded = true;
            foreach(string res in pipe.totalSupply.Keys)
            {
                ret.resourceSupply[res] = pipe.totalSupply[res];
                ret.resourceDemand[res] = pipe.totalDemand[res];
                ret.resourceCapacity[res] = pipe.totalCapacity[res];
                ret.unfocusedProductivity[res] = 0;
            }
            ret.networkDraw = new Dictionary<string,double>();
            foreach(string res in pipe.networkDelta.Keys)
                ret.networkDraw[res] = pipe.networkDelta[res];
           
            return ret;
        }