content: // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  // SPDX-License-Identifier: Apache-2.0
  package com.amazon.ion.impl.lite;
  
  import com.amazon.ion.IonTimestamp;
  import com.amazon.ion.IonType;
  import com.amazon.ion.IonWriter;
  import com.amazon.ion.NullValueException;
  import com.amazon.ion.Timestamp;
  import com.amazon.ion.ValueVisitor;
  import java.io.IOException;
  import java.math.BigDecimal;
  import java.util.Date;
  
  
  final class IonTimestampLite
      extends IonValueLite
      implements IonTimestamp
  {
      public final static Integer UTC_OFFSET = Timestamp.UTC_OFFSET;
  
      private static final int HASH_SIGNATURE =
          IonType.TIMESTAMP.toString().hashCode();
  
  
      private Timestamp _timestamp_value;
  
      /**
       * Constructs a <code>null.timestamp</code> value.
       */
      IonTimestampLite(ContainerlessContext context, boolean isNull)
      {
          super(context, isNull);
      }
  
      IonTimestampLite(IonTimestampLite existing, IonContext context)
      {
          super(existing, context);
          // Timestamp contract is immutable; so can simply pass the reference
          this._timestamp_value = existing._timestamp_value;
      }
  
      @Override
      IonValueLite shallowClone(IonContext context)
      {
          return new IonTimestampLite(this, context);
      }
  
      @Override
      public IonTimestampLite clone()
      {
          return (IonTimestampLite) shallowClone(ContainerlessContext.wrap(getSystem()));
      }
  
      @Override
      int hashSignature() {
          return HASH_SIGNATURE;
      }
  
      @Override
      int scalarHashCode() {
          int result = HASH_SIGNATURE ^ _timestamp_value.hashCode();
          return hashTypeAnnotations(result);
      }
  
      @Override
      public IonType getTypeSlow()
      {
          return IonType.TIMESTAMP;
      }
  
      public Timestamp timestampValue()
      {
          if (isNullValue()) {
              return null;
          }
          return _timestamp_value;
      }
  
      public Date dateValue()
      {
          if (_isNullValue()) {
              return null;
          }
          return _timestamp_value.dateValue();
      }
  
  
      public Integer getLocalOffset() throws NullValueException
      {
          if (_isNullValue()) {
              throw new NullValueException();
          }
          return _timestamp_value.getLocalOffset();
      }
  
  
      /**
       * Returns null if this is null.timestamp.
       */
      private Integer getInternalLocalOffset()
      {
          if (_isNullValue()) {
              return null;
          }
          return _timestamp_value.getLocalOffset();
      }
  
      public void setValue(Timestamp timestamp)
      {
          checkForLock();
          _timestamp_value = timestamp;
          _isNullValue(timestamp == null);
      }
  
      public void setValue(BigDecimal millis, Integer localOffset)
      {
          setValue(new Timestamp(millis, localOffset));
      }
  
      public void setValue(long millis, Integer localOffset)
      {
          setValue(new Timestamp(millis, localOffset));
      }
  
      public void setTime(Date value)
      {
          if (value == null)
          {
              makeNull();
          }
          else
          {
              // setMillis(long) will check for the lock
              setMillis(value.getTime());
          }
      }
  
  
      public BigDecimal getDecimalMillis()
      {
          if (_isNullValue()) {
              return null;
          }
          return _timestamp_value.getDecimalMillis();
      }
  
      public void setDecimalMillis(BigDecimal millis)
      {
          // setValue() calls checkForLock()
          Integer offset = getInternalLocalOffset();
          setValue(millis, offset);
      }
  
  
      public long getMillis()
      {
          if (_isNullValue()) {
              throw new NullValueException();
          }
          return _timestamp_value.getMillis();
      }
  
  
      public void setMillis(long millis)
      {
          // setValue() calls checkForLock()
          Integer offset = getInternalLocalOffset();
          setValue(millis, offset);
      }
  
  
      public void setMillisUtc(long millis)
      {
          // setValue() calls checkForLock()
          setValue(millis, UTC_OFFSET);
      }
  
  
      public void setCurrentTime()
      {
          long millis = System.currentTimeMillis();
          setMillis(millis);
      }
  
      public void setCurrentTimeUtc()
      {
          long millis = System.currentTimeMillis();
          setMillisUtc(millis);
      }
  
      public void setLocalOffset(int minutes)
          throws NullValueException
      {
          // setLocalOffset(Integer) will check for the lock
          setLocalOffset(Integer.valueOf(minutes));
      }
  
  
      public void setLocalOffset(Integer minutes)
          throws NullValueException
      {
          validateThisNotNull();
          assert (_timestamp_value != null);
  
          setValue(_timestamp_value.getDecimalMillis(), minutes);
      }
  
      public void makeNull()
      {
          checkForLock();
          _timestamp_value = null;
          _isNullValue(true);
      }
  
      @Override
      final void writeBodyTo(IonWriter writer, SymbolTableProvider symbolTableProvider)
          throws IOException
      {
          writer.writeTimestamp(_timestamp_value);
      }
  
      @Override
      public void accept(ValueVisitor visitor) throws Exception
      {
          visitor.visit(this);
      }
  }
  