using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text;

[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]
public struct Point3D : INullable
{
   private bool isNull;
   private int x, y, z;

   public override string ToString()
   {
      if (isNull)
         return "NULL";
      else
      {
         StringBuilder sb = new StringBuilder();
         sb.AppendFormat("{0},{1},{2}", x, y, z);
         return sb.ToString();
      }
   }

   public bool IsNull
   {
      get
      {
         // Tu wstaw swój kod
         return isNull;
      }
   }

   public static Point3D Null
   {
      get
      {
         Point3D h = new Point3D();
         h.isNull = true;
         return h;
      }
   }

   // nie wywołuj tej metody jeśli wartość to null
   [SqlMethod(OnNullCall=false)]
   public static Point3D Parse(SqlString s)
   {
      Point3D u = new Point3D();
      string rawValue = s.Value;

      try
      {
         string[] vals = rawValue.Split(',');
         u.x = Int32.Parse(vals[0]);
         u.y = Int32.Parse(vals[1]);
         u.z = Int32.Parse(vals[2]);
      }
      catch(Exception e)
      {
         throw new ArgumentException(
            "Format łańcucha nie jest właściwy dla struktury punktu 3D", e);
      }
      return u;
   }

   [SqlMethod(OnNullCall=false)]
   public Double DistanceFromPoint(Point3D origin)
   {
      return Math.Sqrt(
         (Math.Pow(x - origin.x, 2.0) +
         Math.Pow(y - origin.y, 2.0) +
         Math.Pow(z - origin.z, 2.0)));
   }

   public int X
   {
      get { return x; }
      set { x = value; }
   }

   public int Y
   {
      get { return y; }
      set { y = value; }
   }

   public int Z
   {
      get { return z; }
      set { z = value; }
   }
}
